blob: 780bc13f90f13c7b3994f8d399f2307920b22594 [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"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070018#include "FakeApplicationHandle.h"
Prabir Pradhan81e89fe2024-03-20 21:17:09 +000019#include "FakeInputDispatcherPolicy.h"
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +000020#include "FakeInputTracingBackend.h"
Prabir Pradhanc5340732024-03-20 22:53:52 +000021#include "FakeWindows.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000022#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080023
Cody Heiner166a5af2023-07-07 12:25:00 -070024#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000025#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070026#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080027#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080028#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070029#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070030#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000031#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000032#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000033#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080034#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080035#include <gtest/gtest.h>
Siarhei Vishniakou3782af62024-03-07 21:56:39 -080036#include <input/BlockingQueue.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100037#include <input/Input.h>
Siarhei Vishniakou0438ca82024-03-12 14:27:25 -070038#include <input/InputConsumer.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070039#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080040#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080041#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100042
Garfield Tan1c7bc862020-01-28 13:24:04 -080043#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080044#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070045#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080046#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080047#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080048
Garfield Tan1c7bc862020-01-28 13:24:04 -080049using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050050using android::gui::FocusRequest;
51using android::gui::TouchOcclusionMode;
52using android::gui::WindowInfo;
53using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080054using android::os::InputEventInjectionResult;
55using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080056
Garfield Tane84e6f92019-08-29 17:28:41 -070057namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
Dominik Laskowski2f01d772022-03-23 16:01:29 -070059using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080060using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000061using testing::Not;
Siarhei Vishniakou85eb5802024-04-01 11:40:59 -070062using testing::Pointee;
63using testing::UnorderedElementsAre;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070064
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070065namespace {
66
Michael Wrightd02c5b62014-02-10 15:10:22 -080067// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000068static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080069
70// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000071static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080072static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080073
Jeff Brownf086ddb2014-02-11 14:28:48 -080074// An arbitrary display id.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070075constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
Linnan Li13bf76a2024-05-05 19:18:02 +080076constexpr ui::LogicalDisplayId SECOND_DISPLAY_ID = ui::LogicalDisplayId{1};
Jeff Brownf086ddb2014-02-11 14:28:48 -080077
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000078// Ensure common actions are interchangeable between keys and motions for convenience.
79static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
80static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080081static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
82static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
83static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
84static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070085static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080086static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070087static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080088static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080089static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080090/**
91 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
92 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
93 * index 0) is the new pointer going down. The same pointer could have been placed at a different
94 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
95 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
96 * pointer id=0 leaves but the pointer id=1 remains.
97 */
98static constexpr int32_t POINTER_0_DOWN =
99 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800100static constexpr int32_t POINTER_1_DOWN =
101 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +0000102static constexpr int32_t POINTER_2_DOWN =
103 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +0000104static constexpr int32_t POINTER_3_DOWN =
105 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000106static constexpr int32_t POINTER_0_UP =
107 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800108static constexpr int32_t POINTER_1_UP =
109 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000110static constexpr int32_t POINTER_2_UP =
111 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800112
Antonio Kantek15beb512022-06-13 22:35:41 +0000113// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000114static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000115static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000116
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000117// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000118static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000119
Linnan Li72352222024-04-12 18:55:57 +0800120static constexpr int EXPECTED_WALLPAPER_FLAGS =
Arthur Hungc539dbb2022-12-08 07:45:36 +0000121 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
122
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800123using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
124
Gang Wang342c9272020-01-13 13:15:04 -0500125/**
126 * Return a DOWN key event with KEYCODE_A.
127 */
128static KeyEvent getTestKeyEvent() {
129 KeyEvent event;
130
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700131 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
132 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
133 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500134 return event;
135}
136
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -0700137/**
138 * Provide a local override for a flag value. The value is restored when the object of this class
139 * goes out of scope.
140 * This class is not intended to be used directly, because its usage is cumbersome.
141 * Instead, a wrapper macro SCOPED_FLAG_OVERRIDE is provided.
142 */
143class ScopedFlagOverride {
144public:
145 ScopedFlagOverride(std::function<bool()> read, std::function<void(bool)> write, bool value)
146 : mInitialValue(read()), mWriteValue(write) {
147 mWriteValue(value);
148 }
149 ~ScopedFlagOverride() { mWriteValue(mInitialValue); }
150
151private:
152 const bool mInitialValue;
153 std::function<void(bool)> mWriteValue;
154};
155
156typedef bool (*readFlagValueFunction)();
157typedef void (*writeFlagValueFunction)(bool);
158
159/**
160 * Use this macro to locally override a flag value.
161 * Example usage:
162 * SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
163 * Note: this works by creating a local variable in your current scope. Don't call this twice for
164 * the same flag, because the variable names will clash!
165 */
166#define SCOPED_FLAG_OVERRIDE(NAME, VALUE) \
167 readFlagValueFunction read##NAME = com::android::input::flags::NAME; \
168 writeFlagValueFunction write##NAME = com::android::input::flags::NAME; \
169 ScopedFlagOverride override##NAME(read##NAME, write##NAME, (VALUE))
170
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700171} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800172
Michael Wrightd02c5b62014-02-10 15:10:22 -0800173// --- InputDispatcherTest ---
174
175class InputDispatcherTest : public testing::Test {
176protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000177 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700178 std::unique_ptr<InputDispatcher> mDispatcher;
Prabir Pradhanc5340732024-03-20 22:53:52 +0000179 std::shared_ptr<VerifyingTrace> mVerifyingTrace;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800180
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000181 void SetUp() override {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000182 mVerifyingTrace = std::make_shared<VerifyingTrace>();
183 FakeWindowHandle::sOnEventReceivedCallback = [this](const auto& _1, const auto& _2) {
184 handleEventReceivedByWindow(_1, _2);
185 };
186
Prabir Pradhana41d2442023-04-20 21:30:40 +0000187 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000188 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
189 std::make_unique<FakeInputTracingBackend>(
Prabir Pradhanc5340732024-03-20 22:53:52 +0000190 mVerifyingTrace));
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700191
Harry Cutts101ee9b2023-07-06 18:04:14 +0000192 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000193 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700194 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800195 }
196
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000197 void TearDown() override {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000198 ASSERT_NO_FATAL_FAILURE(mVerifyingTrace->verifyExpectedEventsTraced());
199 FakeWindowHandle::sOnEventReceivedCallback = nullptr;
200
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700201 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000202 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700203 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800204 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700205
Prabir Pradhanc5340732024-03-20 22:53:52 +0000206 void handleEventReceivedByWindow(const std::unique_ptr<InputEvent>& event,
207 const gui::WindowInfo& info) {
208 if (!event) {
209 return;
210 }
211
212 switch (event->getType()) {
213 case InputEventType::KEY: {
214 mVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event), info.id);
215 break;
216 }
217 case InputEventType::MOTION: {
218 mVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event),
219 info.id);
220 break;
221 }
222 default:
223 break;
224 }
225 }
226
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700227 /**
228 * Used for debugging when writing the test
229 */
230 void dumpDispatcherState() {
231 std::string dump;
232 mDispatcher->dump(dump);
233 std::stringstream ss(dump);
234 std::string to;
235
236 while (std::getline(ss, to, '\n')) {
237 ALOGE("%s", to.c_str());
238 }
239 }
Vishnu Nair958da932020-08-21 17:12:37 -0700240
Chavi Weingarten847e8512023-03-29 00:26:09 +0000241 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700242 FocusRequest request;
243 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000244 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700245 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
Linnan Li13bf76a2024-05-05 19:18:02 +0800246 request.displayId = window->getInfo()->displayId.val();
Vishnu Nair958da932020-08-21 17:12:37 -0700247 mDispatcher->setFocusedWindow(request);
248 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800249};
250
Michael Wrightd02c5b62014-02-10 15:10:22 -0800251TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
252 KeyEvent event;
253
254 // Rejects undefined key actions.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700255 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
256 ui::LogicalDisplayId::INVALID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000257 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600258 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800259 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000260 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000261 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800262 << "Should reject key events with undefined action.";
263
264 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700265 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
266 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0,
267 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800268 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000269 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000270 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800271 << "Should reject key events with ACTION_MULTIPLE.";
272}
273
274TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
275 MotionEvent event;
276 PointerProperties pointerProperties[MAX_POINTERS + 1];
277 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800278 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800279 pointerProperties[i].clear();
280 pointerProperties[i].id = i;
281 pointerCoords[i].clear();
282 }
283
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800284 // Some constants commonly used below
285 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
286 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
287 constexpr int32_t metaState = AMETA_NONE;
288 constexpr MotionClassification classification = MotionClassification::NONE;
289
chaviw9eaa22c2020-07-01 16:21:27 -0700290 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800291 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800292 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000293 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700294 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700295 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
296 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000297 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800298 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000299 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000300 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800301 << "Should reject motion events with undefined action.";
302
303 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800304 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800305 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
306 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
307 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
308 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000309 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800310 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000311 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000312 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800313 << "Should reject motion events with pointer down index too large.";
314
Garfield Tanfbe732e2020-01-24 11:26:14 -0800315 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700316 AMOTION_EVENT_ACTION_POINTER_DOWN |
317 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700318 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
319 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700320 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000321 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800322 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000323 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000324 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800325 << "Should reject motion events with pointer down index too small.";
326
327 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800328 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800329 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
330 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
331 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
332 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000333 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800334 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000335 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000336 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800337 << "Should reject motion events with pointer up index too large.";
338
Garfield Tanfbe732e2020-01-24 11:26:14 -0800339 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700340 AMOTION_EVENT_ACTION_POINTER_UP |
341 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700342 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
343 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700344 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000345 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800346 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000347 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000348 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800349 << "Should reject motion events with pointer up index too small.";
350
351 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800352 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
353 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700354 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700355 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
356 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000357 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800358 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000359 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000360 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800361 << "Should reject motion events with 0 pointers.";
362
Garfield Tanfbe732e2020-01-24 11:26:14 -0800363 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
364 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700365 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700366 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
367 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000368 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800369 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000370 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000371 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800372 << "Should reject motion events with more than MAX_POINTERS pointers.";
373
374 // Rejects motion events with invalid pointer ids.
375 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800376 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
377 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700378 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700379 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
380 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000381 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800382 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000383 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000384 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800385 << "Should reject motion events with pointer ids less than 0.";
386
387 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800388 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
389 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700390 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700391 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
392 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000393 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800394 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000395 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000396 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800397 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
398
399 // Rejects motion events with duplicate pointer ids.
400 pointerProperties[0].id = 1;
401 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800402 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
403 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700404 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700405 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
406 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000407 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800408 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000409 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000410 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800411 << "Should reject motion events with duplicate pointer ids.";
412}
413
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800414/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
415
416TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
417 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000418 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800419 ASSERT_TRUE(mDispatcher->waitForIdle());
420
421 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
422}
423
424TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000425 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
426 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000427 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000428 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800429
430 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
431 args.policyFlags |= POLICY_FLAG_TRUSTED;
432 mFakePolicy->assertNotifySwitchWasCalled(args);
433}
434
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700435namespace {
436
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700437static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700438
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000439class FakeMonitorReceiver {
440public:
Linnan Li13bf76a2024-05-05 19:18:02 +0800441 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name,
442 ui::LogicalDisplayId displayId)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700443 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000444
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700445 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000446
Linnan Li13bf76a2024-05-05 19:18:02 +0800447 void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700448 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
449 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000450 }
451
452 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800453 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
454 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000455 }
456
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700457 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000458
Linnan Li13bf76a2024-05-05 19:18:02 +0800459 void consumeMotionDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700460 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
461 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000462 }
463
Linnan Li13bf76a2024-05-05 19:18:02 +0800464 void consumeMotionMove(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700465 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
466 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000467 }
468
Linnan Li13bf76a2024-05-05 19:18:02 +0800469 void consumeMotionUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700470 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
471 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000472 }
473
Linnan Li13bf76a2024-05-05 19:18:02 +0800474 void consumeMotionCancel(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700475 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000476 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
477 WithDisplayId(expectedDisplayId),
478 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
479 }
480
481 void consumeMotionPointerDown(int32_t pointerIdx) {
482 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
483 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700484 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700485 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000486 }
487
488 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700489 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000490 }
491
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800492 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000493
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800494 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000495
496private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700497 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000498};
499
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800500static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700501 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700502 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800503 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800504 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000505 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +0000506 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800507 KeyEvent event;
508 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
509
510 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800511 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +0000512 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
513 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800514
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800515 if (!allowKeyRepeat) {
516 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
517 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800518 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700519 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800520}
521
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700522static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
523 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700524 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
525 ui::LogicalDisplayId::INVALID, InputEventInjectionSync::WAIT_FOR_RESULT,
526 CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700527 if (result != InputEventInjectionResult::TIMED_OUT) {
528 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
529 }
530}
531
Linnan Li13bf76a2024-05-05 19:18:02 +0800532static InputEventInjectionResult injectKeyDown(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700533 InputDispatcher& dispatcher,
534 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000535 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700536}
537
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800538// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
539// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
540// has to be woken up to process the repeating key.
Linnan Li13bf76a2024-05-05 19:18:02 +0800541static InputEventInjectionResult injectKeyDownNoRepeat(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700542 InputDispatcher& dispatcher,
543 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000544 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800545 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +0000546 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800547}
548
Linnan Li13bf76a2024-05-05 19:18:02 +0800549static InputEventInjectionResult injectKeyUp(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700550 InputDispatcher& dispatcher,
551 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000552 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700553}
554
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800555static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700556 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -0700557 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000558 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000559 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700560 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
561 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -0700562}
563
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800564static InputEventInjectionResult injectMotionEvent(
Linnan Li13bf76a2024-05-05 19:18:02 +0800565 InputDispatcher& dispatcher, int32_t action, int32_t source, ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700566 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700567 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700568 AMOTION_EVENT_INVALID_CURSOR_POSITION},
569 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800570 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000571 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000572 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700573 MotionEventBuilder motionBuilder =
574 MotionEventBuilder(action, source)
575 .displayId(displayId)
576 .eventTime(eventTime)
577 .rawXCursorPosition(cursorPosition.x)
578 .rawYCursorPosition(cursorPosition.y)
579 .pointer(
580 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
581 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
582 motionBuilder.downTime(eventTime);
583 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800584
585 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700586 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
587 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800588}
589
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700590static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800591 ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700592 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700593 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -0700594}
595
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700596static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800597 ui::LogicalDisplayId displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800598 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700599 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +0000600}
601
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700602static NotifyKeyArgs generateKeyArgs(
603 int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Jackal Guof9696682018-10-05 12:23:23 +0800604 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
605 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000606 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
607 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
608 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800609
610 return args;
611}
612
Linnan Li13bf76a2024-05-05 19:18:02 +0800613static NotifyKeyArgs generateSystemShortcutArgs(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700614 int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Josep del Riob3981622023-04-18 15:49:45 +0000615 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
616 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000617 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
618 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_C, KEY_C,
619 AMETA_META_ON, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +0000620
621 return args;
622}
623
Linnan Li13bf76a2024-05-05 19:18:02 +0800624static NotifyKeyArgs generateAssistantKeyArgs(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700625 int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Josep del Riob3981622023-04-18 15:49:45 +0000626 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
627 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000628 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
629 AINPUT_SOURCE_KEYBOARD, displayId, 0, action, /*flags=*/0, AKEYCODE_ASSIST,
630 KEY_ASSISTANT, AMETA_NONE, currentTime);
Josep del Riob3981622023-04-18 15:49:45 +0000631
632 return args;
633}
634
Prabir Pradhan678438e2023-04-13 19:32:51 +0000635[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800636 ui::LogicalDisplayId displayId,
Prabir Pradhan678438e2023-04-13 19:32:51 +0000637 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -0800638 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700639 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
640 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
641 }
642
chaviwd1c23182019-12-20 18:44:56 -0800643 PointerProperties pointerProperties[pointerCount];
644 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800645
chaviwd1c23182019-12-20 18:44:56 -0800646 for (size_t i = 0; i < pointerCount; i++) {
647 pointerProperties[i].clear();
648 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -0700649 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800650
chaviwd1c23182019-12-20 18:44:56 -0800651 pointerCoords[i].clear();
652 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
653 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
654 }
Jackal Guof9696682018-10-05 12:23:23 +0800655
656 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
657 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000658 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
659 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
660 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800661 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000662 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700663 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000664 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +0800665
666 return args;
667}
668
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800669static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
670 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
671}
672
Linnan Li13bf76a2024-05-05 19:18:02 +0800673static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
674 ui::LogicalDisplayId displayId) {
chaviwd1c23182019-12-20 18:44:56 -0800675 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
676}
677
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000678static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
679 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000680 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
681 request);
Prabir Pradhan99987712020-11-10 18:43:05 -0800682}
683
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700684} // namespace
685
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800686/**
687 * When a window unexpectedly disposes of its input channel, policy should be notified about the
688 * broken channel.
689 */
690TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
691 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700692 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
693 "Window that breaks its input channel",
694 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800695
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700696 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800697
698 // Window closes its channel, but the window remains.
699 window->destroyReceiver();
700 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
701}
702
Arthur Hungb92218b2018-08-14 12:00:21 +0800703TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700705 sp<FakeWindowHandle> window =
706 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
707 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800708
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700709 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800710 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700711 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
712 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800713 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800714
715 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700716 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800717}
718
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800719using InputDispatcherDeathTest = InputDispatcherTest;
720
721/**
722 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
723 * should crash.
724 */
725TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
726 testing::GTEST_FLAG(death_test_style) = "threadsafe";
727 ScopedSilentDeath _silentDeath;
728
729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700730 sp<FakeWindowHandle> window =
731 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
732 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800733 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
734 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
735 "Incorrect WindowInfosUpdate provided");
736}
737
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700738TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
739 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700740 sp<FakeWindowHandle> window =
741 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
742 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700743
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700744 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700745 // Inject a MotionEvent to an unknown display.
746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700747 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
748 ui::LogicalDisplayId::INVALID))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700749 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
750
751 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700752 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700753}
754
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700755/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700756 * Calling onWindowInfosChanged once should not cause any issues.
757 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700758 * called twice.
759 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -0800760TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -0700761 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700762 sp<FakeWindowHandle> window =
763 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
764 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700765 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700766
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700767 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800768 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700769 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
770 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800771 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700772
773 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700774 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700775}
776
777/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700778 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700779 */
780TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700781 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700782 sp<FakeWindowHandle> window =
783 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
784 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700785 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700786
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700787 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
788 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700790 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
791 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800792 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700793
794 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700795 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700796}
797
Arthur Hungb92218b2018-08-14 12:00:21 +0800798// The foreground window should receive the first touch down event.
799TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700800 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700801 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
802 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000803 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700804 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
805 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800806
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700807 mDispatcher->onWindowInfosChanged(
808 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700810 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
811 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800812 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800813
814 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700815 windowTop->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800816 windowSecond->assertNoEvents();
817}
818
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000819/**
820 * Two windows: A top window, and a wallpaper behind the window.
821 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
822 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800823 * 1. foregroundWindow <-- dup touch to wallpaper
824 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000825 */
826TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
827 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
828 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700829 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
830 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800831 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000832 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700833 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
834 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800835 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000836
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700837 mDispatcher->onWindowInfosChanged(
838 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800840 injectMotionEvent(*mDispatcher,
841 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
842 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
843 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000844 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
845
846 // Both foreground window and its wallpaper should receive the touch down
847 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700848 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000849
850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800851 injectMotionEvent(*mDispatcher,
852 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
853 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
854 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000855 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
856
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800857 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700858 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000859
860 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700861 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000862 foregroundWindow->consumeMotionCancel();
863 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700864 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000865}
866
867/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800868 * Two fingers down on the window, and lift off the first finger.
869 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
870 * contains a single pointer.
871 */
872TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
873 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700874 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
875 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800876
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700877 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800878 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +0000879 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
880 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
881 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800882 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000883 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
884 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
885 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
886 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800887 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000888 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
889 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
890 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
891 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800892 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
893 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
894 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
895
896 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700897 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800898 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
899 window->consumeMotionEvent(
900 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
901}
902
903/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800904 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
905 * with the following differences:
906 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
907 * clean up the connection.
908 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
909 * Ensure that there's no crash in the dispatcher.
910 */
911TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
912 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
913 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700914 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
915 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800916 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800917 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700918 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
919 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800920 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800921
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700922 mDispatcher->onWindowInfosChanged(
923 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800924 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700925 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
926 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800927 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
928
929 // Both foreground window and its wallpaper should receive the touch down
930 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700931 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800932
933 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700934 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700935 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800936 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
937
938 foregroundWindow->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700939 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800940
941 // Wallpaper closes its channel, but the window remains.
942 wallpaperWindow->destroyReceiver();
943 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
944
945 // Now the foreground window goes away, but the wallpaper stays, even though its channel
946 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700947 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800948 foregroundWindow->consumeMotionCancel();
949}
950
Linnan Li72352222024-04-12 18:55:57 +0800951/**
952 * Two windows: left and right, and a separate wallpaper window underneath each. Device A sends a
953 * down event to the left window. Device B sends a down event to the right window. Next, the right
954 * window disappears. Both the right window and its wallpaper window should receive cancel event.
955 * The left window and its wallpaper window should not receive any events.
956 */
957TEST_F(InputDispatcherTest, MultiDeviceDisappearingWindowWithWallpaperWindows) {
958 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
959 sp<FakeWindowHandle> leftForegroundWindow =
960 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700961 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800962 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
963 leftForegroundWindow->setDupTouchToWallpaper(true);
964 sp<FakeWindowHandle> leftWallpaperWindow =
965 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700966 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800967 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
968 leftWallpaperWindow->setIsWallpaper(true);
969
970 sp<FakeWindowHandle> rightForegroundWindow =
971 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700972 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800973 rightForegroundWindow->setFrame(Rect(100, 0, 200, 100));
974 rightForegroundWindow->setDupTouchToWallpaper(true);
975 sp<FakeWindowHandle> rightWallpaperWindow =
976 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700977 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800978 rightWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
979 rightWallpaperWindow->setIsWallpaper(true);
980
981 mDispatcher->onWindowInfosChanged(
982 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
983 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
984 {},
985 0,
986 0});
987
988 const DeviceId deviceA = 9;
989 const DeviceId deviceB = 3;
990 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
991 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
992 .deviceId(deviceA)
993 .build());
994 leftForegroundWindow->consumeMotionEvent(
995 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
996 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
997 WithDeviceId(deviceA),
998 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
999
1000 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1001 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1002 .deviceId(deviceB)
1003 .build());
1004 rightForegroundWindow->consumeMotionEvent(
1005 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1006 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1007 WithDeviceId(deviceB),
1008 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1009
1010 // Now right foreground window disappears, but right wallpaper window remains.
1011 mDispatcher->onWindowInfosChanged(
1012 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1013 *rightWallpaperWindow->getInfo()},
1014 {},
1015 0,
1016 0});
1017
1018 // Left foreground window and left wallpaper window still exist, and should not receive any
1019 // events.
1020 leftForegroundWindow->assertNoEvents();
1021 leftWallpaperWindow->assertNoEvents();
1022 // Since right foreground window disappeared, right wallpaper window and right foreground window
1023 // should receive cancel events.
1024 rightForegroundWindow->consumeMotionEvent(
1025 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1026 rightWallpaperWindow->consumeMotionEvent(
1027 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1028 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1029}
1030
1031/**
1032 * Three windows arranged horizontally and without any overlap. Every window has a
1033 * wallpaper window underneath. The middle window also has SLIPPERY flag.
1034 * Device A sends a down event to the left window. Device B sends a down event to the middle window.
1035 * Next, device B sends move event to the right window. Touch for device B should slip from the
1036 * middle window to the right window. Also, the right wallpaper window should receive a down event.
1037 * The middle window and its wallpaper window should receive a cancel event. The left window should
1038 * not receive any events. If device B continues to report events, the right window and its
1039 * wallpaper window should receive remaining events.
1040 */
1041TEST_F(InputDispatcherTest, MultiDeviceSlipperyTouchWithWallpaperWindow) {
1042 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1043 sp<FakeWindowHandle> leftForegroundWindow =
1044 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001045 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001046 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1047 leftForegroundWindow->setDupTouchToWallpaper(true);
1048 sp<FakeWindowHandle> leftWallpaperWindow =
1049 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001050 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001051 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1052 leftWallpaperWindow->setIsWallpaper(true);
1053
1054 sp<FakeWindowHandle> middleForegroundWindow =
1055 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001056 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001057 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1058 middleForegroundWindow->setDupTouchToWallpaper(true);
1059 middleForegroundWindow->setSlippery(true);
1060 sp<FakeWindowHandle> middleWallpaperWindow =
1061 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001062 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001063 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1064 middleWallpaperWindow->setIsWallpaper(true);
1065
1066 sp<FakeWindowHandle> rightForegroundWindow =
1067 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001068 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001069 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1070 rightForegroundWindow->setDupTouchToWallpaper(true);
1071 sp<FakeWindowHandle> rightWallpaperWindow =
1072 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001073 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001074 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1075 rightWallpaperWindow->setIsWallpaper(true);
1076
1077 mDispatcher->onWindowInfosChanged(
1078 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1079 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1080 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1081 {},
1082 0,
1083 0});
1084
1085 const DeviceId deviceA = 9;
1086 const DeviceId deviceB = 3;
1087 // Device A sends a DOWN event to the left window
1088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1089 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1090 .deviceId(deviceA)
1091 .build());
1092 leftForegroundWindow->consumeMotionEvent(
1093 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1094 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1095 WithDeviceId(deviceA),
1096 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1097 // Device B sends a DOWN event to the middle window
1098 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1099 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1100 .deviceId(deviceB)
1101 .build());
1102 middleForegroundWindow->consumeMotionEvent(
1103 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1104 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1105 WithDeviceId(deviceB),
1106 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1107 // Move the events of device B to the top of the right window.
1108 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1109 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
1110 .deviceId(deviceB)
1111 .build());
1112 middleForegroundWindow->consumeMotionEvent(
1113 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1114 middleWallpaperWindow->consumeMotionEvent(
1115 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1116 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1117 rightForegroundWindow->consumeMotionEvent(
1118 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1119 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1120 WithDeviceId(deviceB),
1121 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1122 // Make sure the window on the right can receive the remaining events.
1123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1124 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1125 .deviceId(deviceB)
1126 .build());
1127 leftForegroundWindow->assertNoEvents();
1128 leftWallpaperWindow->assertNoEvents();
1129 middleForegroundWindow->assertNoEvents();
1130 middleWallpaperWindow->assertNoEvents();
1131 rightForegroundWindow->consumeMotionEvent(
1132 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
1133 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1134 WithDeviceId(deviceB),
1135 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1136}
1137
1138/**
1139 * Similar to the test above, we have three windows, they are arranged horizontally and without any
1140 * overlap, and every window has a wallpaper window. The middle window is a simple window, without
1141 * any special flags. Device A reports a down event that lands in left window. Device B sends a down
1142 * event to the middle window and then touch is transferred from the middle window to the right
1143 * window. The right window and its wallpaper window should receive a down event. The middle window
1144 * and its wallpaper window should receive a cancel event. The left window should not receive any
1145 * events. Subsequent events reported by device B should go to the right window and its wallpaper.
1146 */
1147TEST_F(InputDispatcherTest, MultiDeviceTouchTransferWithWallpaperWindows) {
1148 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1149 sp<FakeWindowHandle> leftForegroundWindow =
1150 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001151 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001152 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1153 leftForegroundWindow->setDupTouchToWallpaper(true);
1154 sp<FakeWindowHandle> leftWallpaperWindow =
1155 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001156 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001157 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1158 leftWallpaperWindow->setIsWallpaper(true);
1159
1160 sp<FakeWindowHandle> middleForegroundWindow =
1161 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001162 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001163 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1164 middleForegroundWindow->setDupTouchToWallpaper(true);
1165 sp<FakeWindowHandle> middleWallpaperWindow =
1166 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001167 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001168 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1169 middleWallpaperWindow->setIsWallpaper(true);
1170
1171 sp<FakeWindowHandle> rightForegroundWindow =
1172 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001173 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001174 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1175 rightForegroundWindow->setDupTouchToWallpaper(true);
1176 sp<FakeWindowHandle> rightWallpaperWindow =
1177 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001178 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001179 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1180 rightWallpaperWindow->setIsWallpaper(true);
1181
1182 mDispatcher->onWindowInfosChanged(
1183 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1184 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1185 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1186 {},
1187 0,
1188 0});
1189
1190 const DeviceId deviceA = 9;
1191 const DeviceId deviceB = 3;
1192 // Device A touch down on the left window
1193 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1194 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1195 .deviceId(deviceA)
1196 .build());
1197 leftForegroundWindow->consumeMotionEvent(
1198 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1199 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1200 WithDeviceId(deviceA),
1201 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1202 // Device B touch down on the middle window
1203 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1204 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1205 .deviceId(deviceB)
1206 .build());
1207 middleForegroundWindow->consumeMotionEvent(
1208 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1209 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1210 WithDeviceId(deviceB),
1211 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1212
1213 // Transfer touch from the middle window to the right window.
1214 ASSERT_TRUE(mDispatcher->transferTouchGesture(middleForegroundWindow->getToken(),
1215 rightForegroundWindow->getToken()));
1216
1217 middleForegroundWindow->consumeMotionEvent(
1218 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1219 middleWallpaperWindow->consumeMotionEvent(
1220 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1221 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1222 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1223 WithDeviceId(deviceB),
1224 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1225 rightWallpaperWindow->consumeMotionEvent(
1226 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
1227 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1228
1229 // Make sure the right window can receive the remaining events.
1230 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1231 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1232 .deviceId(deviceB)
1233 .build());
1234 leftForegroundWindow->assertNoEvents();
1235 leftWallpaperWindow->assertNoEvents();
1236 middleForegroundWindow->assertNoEvents();
1237 middleWallpaperWindow->assertNoEvents();
1238 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1239 WithDeviceId(deviceB),
1240 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1241 rightWallpaperWindow->consumeMotionEvent(
1242 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB),
1243 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1244}
1245
Arthur Hungc539dbb2022-12-08 07:45:36 +00001246class ShouldSplitTouchFixture : public InputDispatcherTest,
1247 public ::testing::WithParamInterface<bool> {};
1248INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1249 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001250/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001251 * A single window that receives touch (on top), and a wallpaper window underneath it.
1252 * The top window gets a multitouch gesture.
1253 * Ensure that wallpaper gets the same gesture.
1254 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001255TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001256 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001257 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001258 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
1259 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001260 foregroundWindow->setDupTouchToWallpaper(true);
1261 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001262
1263 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001264 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1265 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001266 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001267
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001268 mDispatcher->onWindowInfosChanged(
1269 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001270
1271 // Touch down on top window
1272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001273 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1274 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001275 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1276
1277 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001278 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001279 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001280
1281 // Second finger down on the top window
1282 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001283 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001284 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001285 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1286 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001287 .build();
1288 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001289 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001290 InputEventInjectionSync::WAIT_FOR_RESULT))
1291 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00001292 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001293 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001294 EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001295
1296 const MotionEvent secondFingerUpEvent =
1297 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001298 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hungc539dbb2022-12-08 07:45:36 +00001299 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001300 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1301 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001302 .build();
1303 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001304 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001305 InputEventInjectionSync::WAIT_FOR_RESULT))
1306 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1307 foregroundWindow->consumeMotionPointerUp(0);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001308 wallpaperWindow->consumeMotionPointerUp(0, ui::LogicalDisplayId::DEFAULT,
1309 EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001310
1311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001312 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001313 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1314 AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001315 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001316 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001317 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001318 .x(100)
1319 .y(100))
1320 .build(),
1321 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001322 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001323 foregroundWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
1324 wallpaperWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001325}
1326
1327/**
1328 * Two windows: a window on the left and window on the right.
1329 * A third window, wallpaper, is behind both windows, and spans both top windows.
1330 * The first touch down goes to the left window. A second pointer touches down on the right window.
1331 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1332 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1333 * ACTION_POINTER_DOWN(1).
1334 */
1335TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1336 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001337 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1338 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001339 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001340 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001341
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001342 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1343 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001344 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001345 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001346
1347 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001348 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1349 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001350 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001351 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001352
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001353 mDispatcher->onWindowInfosChanged(
1354 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1355 {},
1356 0,
1357 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001358
1359 // Touch down on left window
1360 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001361 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1362 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001363 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1364
1365 // Both foreground window and its wallpaper should receive the touch down
1366 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001367 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001368
1369 // Second finger down on the right window
1370 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001371 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001372 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001373 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1374 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001375 .build();
1376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001377 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001378 InputEventInjectionSync::WAIT_FOR_RESULT))
1379 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1380
1381 leftWindow->consumeMotionMove();
1382 // Since the touch is split, right window gets ACTION_DOWN
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001383 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1384 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001385 EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001386
1387 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001388 mDispatcher->onWindowInfosChanged(
1389 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001390 leftWindow->consumeMotionCancel();
1391 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001392 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001393
1394 // The pointer that's still down on the right window moves, and goes to the right window only.
1395 // As far as the dispatcher's concerned though, both pointers are still present.
1396 const MotionEvent secondFingerMoveEvent =
1397 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1398 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001399 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1400 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001401 .build();
1402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001403 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001404 InputEventInjectionSync::WAIT_FOR_RESULT));
1405 rightWindow->consumeMotionMove();
1406
1407 leftWindow->assertNoEvents();
1408 rightWindow->assertNoEvents();
1409 wallpaperWindow->assertNoEvents();
1410}
1411
Arthur Hungc539dbb2022-12-08 07:45:36 +00001412/**
1413 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
1414 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
1415 * The right window should receive ACTION_DOWN.
1416 */
1417TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00001418 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001419 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1420 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001421 leftWindow->setFrame(Rect(0, 0, 200, 200));
1422 leftWindow->setDupTouchToWallpaper(true);
1423 leftWindow->setSlippery(true);
1424
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001425 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1426 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001427 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00001428
1429 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001430 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1431 ui::LogicalDisplayId::DEFAULT);
Arthur Hung74c248d2022-11-23 07:09:59 +00001432 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00001433
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001434 mDispatcher->onWindowInfosChanged(
1435 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1436 {},
1437 0,
1438 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00001439
Arthur Hungc539dbb2022-12-08 07:45:36 +00001440 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00001441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001442 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1443 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001444 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00001445
1446 // Both foreground window and its wallpaper should receive the touch down
1447 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001448 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001449
Arthur Hungc539dbb2022-12-08 07:45:36 +00001450 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00001451 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001452 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001453 ui::LogicalDisplayId::DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001454 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1455
Arthur Hungc539dbb2022-12-08 07:45:36 +00001456 leftWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001457 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1458 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001459}
1460
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001461/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001462 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1463 * interactive, it might stop sending this flag.
1464 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
1465 * to have a consistent input stream.
1466 *
1467 * Test procedure:
1468 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
1469 * DOWN (new gesture).
1470 *
1471 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
1472 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
1473 *
1474 * We technically just need a single window here, but we are using two windows (spy on top and a
1475 * regular window below) to emulate the actual situation where it happens on the device.
1476 */
1477TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
1478 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001479 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
1480 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001481 spyWindow->setFrame(Rect(0, 0, 200, 200));
1482 spyWindow->setTrustedOverlay(true);
1483 spyWindow->setSpy(true);
1484
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001485 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1486 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001487 window->setFrame(Rect(0, 0, 200, 200));
1488
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001489 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001490 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001491
1492 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001493 mDispatcher->notifyMotion(
1494 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1495 .deviceId(touchDeviceId)
1496 .policyFlags(DEFAULT_POLICY_FLAGS)
1497 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1498 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001499
Prabir Pradhan678438e2023-04-13 19:32:51 +00001500 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1501 .deviceId(touchDeviceId)
1502 .policyFlags(DEFAULT_POLICY_FLAGS)
1503 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1504 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1505 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001506 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1507 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1508 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1509 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1510
1511 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001512 mDispatcher->notifyMotion(
1513 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
1514 .deviceId(touchDeviceId)
1515 .policyFlags(0)
1516 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1517 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1518 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001519 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1520 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1521
1522 // We don't need to reset the device to reproduce the issue, but the reset event typically
1523 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001524 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001525
1526 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00001527 mDispatcher->notifyMotion(
1528 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1529 .deviceId(touchDeviceId)
1530 .policyFlags(DEFAULT_POLICY_FLAGS)
1531 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1532 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001533 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1534 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1535
1536 // No more events
1537 spyWindow->assertNoEvents();
1538 window->assertNoEvents();
1539}
1540
1541/**
Linnan Li907ae732023-09-05 17:14:21 +08001542 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
1543 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1544 * interactive, it might stop sending this flag.
1545 * We've already ensured the consistency of the touch event in this case, and we should also ensure
1546 * the consistency of the hover event in this case.
1547 *
1548 * Test procedure:
1549 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
1550 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
1551 *
1552 * We expect to receive two full streams of hover events.
1553 */
1554TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
1555 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1556
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001557 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1558 ui::LogicalDisplayId::DEFAULT);
Linnan Li907ae732023-09-05 17:14:21 +08001559 window->setFrame(Rect(0, 0, 300, 300));
1560
1561 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1562
1563 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1564 .policyFlags(DEFAULT_POLICY_FLAGS)
1565 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
1566 .build());
1567 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1568
1569 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1570 .policyFlags(DEFAULT_POLICY_FLAGS)
1571 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1572 .build());
1573 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1574
1575 // Send hover exit without the default policy flags.
1576 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1577 .policyFlags(0)
1578 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1579 .build());
1580
1581 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1582
1583 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
1584 // right event.
1585 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1586 .policyFlags(DEFAULT_POLICY_FLAGS)
1587 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
1588 .build());
1589 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1590
1591 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1592 .policyFlags(DEFAULT_POLICY_FLAGS)
1593 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1594 .build());
1595 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1596
1597 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1598 .policyFlags(DEFAULT_POLICY_FLAGS)
1599 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1600 .build());
1601 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1602}
1603
1604/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001605 * Two windows: a window on the left and a window on the right.
1606 * Mouse is hovered from the right window into the left window.
1607 * Next, we tap on the left window, where the cursor was last seen.
1608 * The second tap is done onto the right window.
1609 * The mouse and tap are from two different devices.
1610 * We technically don't need to set the downtime / eventtime for these events, but setting these
1611 * explicitly helps during debugging.
1612 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1613 * In the buggy implementation, a tap on the right window would cause a crash.
1614 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001615TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap_legacy) {
1616 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
1617
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001618 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001619 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1620 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001621 leftWindow->setFrame(Rect(0, 0, 200, 200));
1622
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001623 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1624 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001625 rightWindow->setFrame(Rect(200, 0, 400, 200));
1626
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001627 mDispatcher->onWindowInfosChanged(
1628 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001629 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1630 // stale.
1631 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1632 const int32_t mouseDeviceId = 6;
1633 const int32_t touchDeviceId = 4;
1634 // Move the cursor from right
1635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001636 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001637 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1638 AINPUT_SOURCE_MOUSE)
1639 .deviceId(mouseDeviceId)
1640 .downTime(baseTime + 10)
1641 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001642 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001643 .build()));
1644 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1645
1646 // .. to the left window
1647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001648 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001649 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1650 AINPUT_SOURCE_MOUSE)
1651 .deviceId(mouseDeviceId)
1652 .downTime(baseTime + 10)
1653 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001654 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001655 .build()));
1656 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1657 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1658 // Now tap the left window
1659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001660 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001661 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1662 AINPUT_SOURCE_TOUCHSCREEN)
1663 .deviceId(touchDeviceId)
1664 .downTime(baseTime + 40)
1665 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001666 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001667 .build()));
1668 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1669 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1670
1671 // release tap
1672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001673 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001674 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1675 AINPUT_SOURCE_TOUCHSCREEN)
1676 .deviceId(touchDeviceId)
1677 .downTime(baseTime + 40)
1678 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001679 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001680 .build()));
1681 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1682
1683 // Tap the window on the right
1684 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001685 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001686 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1687 AINPUT_SOURCE_TOUCHSCREEN)
1688 .deviceId(touchDeviceId)
1689 .downTime(baseTime + 60)
1690 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001691 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001692 .build()));
1693 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1694
1695 // release tap
1696 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001697 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001698 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1699 AINPUT_SOURCE_TOUCHSCREEN)
1700 .deviceId(touchDeviceId)
1701 .downTime(baseTime + 60)
1702 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001703 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001704 .build()));
1705 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1706
1707 // No more events
1708 leftWindow->assertNoEvents();
1709 rightWindow->assertNoEvents();
1710}
1711
1712/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001713 * Two windows: a window on the left and a window on the right.
1714 * Mouse is hovered from the right window into the left window.
1715 * Next, we tap on the left window, where the cursor was last seen.
1716 * The second tap is done onto the right window.
1717 * The mouse and tap are from two different devices.
1718 * We technically don't need to set the downtime / eventtime for these events, but setting these
1719 * explicitly helps during debugging.
1720 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1721 * In the buggy implementation, a tap on the right window would cause a crash.
1722 */
1723TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
1724 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1725
1726 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001727 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1728 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001729 leftWindow->setFrame(Rect(0, 0, 200, 200));
1730
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001731 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1732 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001733 rightWindow->setFrame(Rect(200, 0, 400, 200));
1734
1735 mDispatcher->onWindowInfosChanged(
1736 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
1737 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1738 // stale.
1739 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1740 const int32_t mouseDeviceId = 6;
1741 const int32_t touchDeviceId = 4;
1742 // Move the cursor from right
1743 mDispatcher->notifyMotion(
1744 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1745 .deviceId(mouseDeviceId)
1746 .downTime(baseTime + 10)
1747 .eventTime(baseTime + 20)
1748 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
1749 .build());
1750 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1751
1752 // .. to the left window
1753 mDispatcher->notifyMotion(
1754 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1755 .deviceId(mouseDeviceId)
1756 .downTime(baseTime + 10)
1757 .eventTime(baseTime + 30)
1758 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
1759 .build());
1760 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1761 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1762 // Now tap the left window
1763 mDispatcher->notifyMotion(
1764 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1765 .deviceId(touchDeviceId)
1766 .downTime(baseTime + 40)
1767 .eventTime(baseTime + 40)
1768 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1769 .build());
1770 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1771
1772 // release tap
1773 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1774 .deviceId(touchDeviceId)
1775 .downTime(baseTime + 40)
1776 .eventTime(baseTime + 50)
1777 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1778 .build());
1779 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1780
1781 // Tap the window on the right
1782 mDispatcher->notifyMotion(
1783 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1784 .deviceId(touchDeviceId)
1785 .downTime(baseTime + 60)
1786 .eventTime(baseTime + 60)
1787 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1788 .build());
1789 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1790
1791 // release tap
1792 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1793 .deviceId(touchDeviceId)
1794 .downTime(baseTime + 60)
1795 .eventTime(baseTime + 70)
1796 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1797 .build());
1798 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1799
1800 // No more events
1801 leftWindow->assertNoEvents();
1802 rightWindow->assertNoEvents();
1803}
1804
1805/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001806 * Start hovering in a window. While this hover is still active, make another window appear on top.
1807 * The top, obstructing window has no input channel, so it's not supposed to receive input.
1808 * While the top window is present, the hovering is stopped.
1809 * Later, hovering gets resumed again.
1810 * Ensure that new hover gesture is handled correctly.
1811 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
1812 * to the window that's currently being hovered over.
1813 */
1814TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
1815 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001816 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1817 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001818 window->setFrame(Rect(0, 0, 200, 200));
1819
1820 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001821 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001822
1823 // Start hovering in the window
1824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1825 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1826 .build());
1827 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1828
1829 // Now, an obscuring window appears!
1830 sp<FakeWindowHandle> obscuringWindow =
1831 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001832 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001833 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001834 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1835 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1836 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1837 obscuringWindow->setNoInputChannel(true);
1838 obscuringWindow->setFocusable(false);
1839 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001840 mDispatcher->onWindowInfosChanged(
1841 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001842
1843 // While this new obscuring window is present, the hovering is stopped
1844 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1845 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1846 .build());
1847 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1848
1849 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001850 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001851
1852 // And a new hover gesture starts.
1853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1854 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1855 .build());
1856 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1857}
1858
1859/**
1860 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
1861 * the obscuring window.
1862 */
1863TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
1864 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001865 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1866 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001867 window->setFrame(Rect(0, 0, 200, 200));
1868
1869 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001870 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001871
1872 // Start hovering in the window
1873 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1874 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1875 .build());
1876 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1877
1878 // Now, an obscuring window appears!
1879 sp<FakeWindowHandle> obscuringWindow =
1880 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001881 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001882 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001883 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1884 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1885 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1886 obscuringWindow->setNoInputChannel(true);
1887 obscuringWindow->setFocusable(false);
1888 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001889 mDispatcher->onWindowInfosChanged(
1890 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001891
1892 // While this new obscuring window is present, the hovering continues. The event can't go to the
1893 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
1894 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1895 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1896 .build());
1897 obscuringWindow->assertNoEvents();
1898 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1899
1900 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001901 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001902
1903 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
1904 // so it should generate a HOVER_ENTER
1905 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1906 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1907 .build());
1908 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1909
1910 // Now the MOVE should be getting dispatched normally
1911 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1912 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
1913 .build());
1914 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1915}
1916
1917/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001918 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
1919 * events are delivered to the window.
1920 */
1921TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
1922 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001923 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1924 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001925 window->setFrame(Rect(0, 0, 200, 200));
1926 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1927
1928 // Start hovering in the window
1929 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
1930 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1931 .build());
1932 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1933
1934 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1935 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1936 .build());
1937 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1938
1939 // Scroll with the mouse
1940 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
1941 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1942 .build());
1943 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
1944}
1945
1946using InputDispatcherMultiDeviceTest = InputDispatcherTest;
1947
1948/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001949 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
1950 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001951 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001952TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001953 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001954 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001955 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1956 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001957 window->setFrame(Rect(0, 0, 200, 200));
1958
1959 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1960
1961 constexpr int32_t touchDeviceId = 4;
1962 constexpr int32_t stylusDeviceId = 2;
1963
1964 // Stylus down
1965 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1966 .deviceId(stylusDeviceId)
1967 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
1968 .build());
1969 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
1970
1971 // Touch down
1972 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1973 .deviceId(touchDeviceId)
1974 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
1975 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001976
1977 // Touch move
1978 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1979 .deviceId(touchDeviceId)
1980 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
1981 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001982 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001983
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001984 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001985 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
1986 .deviceId(stylusDeviceId)
1987 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
1988 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001989 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
1990 WithCoords(101, 111)));
1991
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001992 window->assertNoEvents();
1993}
1994
1995/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001996 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
1997 * touch is not dropped, because multiple devices are allowed to be active in the same window.
1998 */
1999TEST_F(InputDispatcherMultiDeviceTest, StylusDownDoesNotBlockTouchDown) {
2000 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2001 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002002 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2003 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002004 window->setFrame(Rect(0, 0, 200, 200));
2005
2006 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2007
2008 constexpr int32_t touchDeviceId = 4;
2009 constexpr int32_t stylusDeviceId = 2;
2010
2011 // Stylus down
2012 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2013 .deviceId(stylusDeviceId)
2014 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2015 .build());
2016 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2017
2018 // Touch down
2019 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2020 .deviceId(touchDeviceId)
2021 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2022 .build());
2023 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2024
2025 // Touch move
2026 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2027 .deviceId(touchDeviceId)
2028 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2029 .build());
2030 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2031
2032 // Stylus move
2033 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2034 .deviceId(stylusDeviceId)
2035 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2036 .build());
2037 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2038 WithCoords(101, 111)));
2039
2040 window->assertNoEvents();
2041}
2042
2043/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002044 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002045 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002046 * Similar test as above, but with added SPY window.
2047 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002048TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002049 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002050 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002051 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2052 ui::LogicalDisplayId::DEFAULT);
2053 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2054 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002055 spyWindow->setFrame(Rect(0, 0, 200, 200));
2056 spyWindow->setTrustedOverlay(true);
2057 spyWindow->setSpy(true);
2058 window->setFrame(Rect(0, 0, 200, 200));
2059
2060 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2061
2062 constexpr int32_t touchDeviceId = 4;
2063 constexpr int32_t stylusDeviceId = 2;
2064
2065 // Stylus down
2066 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2067 .deviceId(stylusDeviceId)
2068 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2069 .build());
2070 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2071 spyWindow->consumeMotionEvent(
2072 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2073
2074 // Touch down
2075 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2076 .deviceId(touchDeviceId)
2077 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2078 .build());
2079
2080 // Touch move
2081 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2082 .deviceId(touchDeviceId)
2083 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2084 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002085
2086 // Touch is ignored because stylus is already down
2087
2088 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002089 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2090 .deviceId(stylusDeviceId)
2091 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2092 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002093 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2094 WithCoords(101, 111)));
2095 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2096 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002097
2098 window->assertNoEvents();
2099 spyWindow->assertNoEvents();
2100}
2101
2102/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002103 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2104 * down. Ensure that touch is not dropped, because multiple devices can be active at the same time.
2105 * Similar test as above, but with added SPY window.
2106 */
2107TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyDoesNotBlockTouchDown) {
2108 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2109 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002110 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2111 ui::LogicalDisplayId::DEFAULT);
2112 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2113 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002114 spyWindow->setFrame(Rect(0, 0, 200, 200));
2115 spyWindow->setTrustedOverlay(true);
2116 spyWindow->setSpy(true);
2117 window->setFrame(Rect(0, 0, 200, 200));
2118
2119 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2120
2121 constexpr int32_t touchDeviceId = 4;
2122 constexpr int32_t stylusDeviceId = 2;
2123
2124 // Stylus down
2125 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2126 .deviceId(stylusDeviceId)
2127 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2128 .build());
2129 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2130 spyWindow->consumeMotionEvent(
2131 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2132
2133 // Touch down
2134 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2135 .deviceId(touchDeviceId)
2136 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2137 .build());
2138 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2139 spyWindow->consumeMotionEvent(
2140 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2141
2142 // Touch move
2143 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2144 .deviceId(touchDeviceId)
2145 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2146 .build());
2147 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2148 spyWindow->consumeMotionEvent(
2149 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2150
2151 // Subsequent stylus movements are delivered correctly
2152 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2153 .deviceId(stylusDeviceId)
2154 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2155 .build());
2156 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2157 WithCoords(101, 111)));
2158 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2159 WithCoords(101, 111)));
2160
2161 window->assertNoEvents();
2162 spyWindow->assertNoEvents();
2163}
2164
2165/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002166 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002167 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002168 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002169TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002170 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002171 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002172 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2173 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002174 window->setFrame(Rect(0, 0, 200, 200));
2175
2176 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2177
2178 constexpr int32_t touchDeviceId = 4;
2179 constexpr int32_t stylusDeviceId = 2;
2180
2181 // Stylus down on the window
2182 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2183 .deviceId(stylusDeviceId)
2184 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2185 .build());
2186 window->consumeMotionEvent(
2187 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2188
2189 // Touch down on window
2190 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2191 .deviceId(touchDeviceId)
2192 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2193 .build());
2194 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2195 .deviceId(touchDeviceId)
2196 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2197 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002198
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002199 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002200
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002201 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002202 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2203 .deviceId(stylusDeviceId)
2204 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2205 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002206 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2207 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002208
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002209 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002210 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2211 .deviceId(touchDeviceId)
2212 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2213 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002214 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002215}
2216
2217/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002218 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2219 * touch is not dropped, because stylus hover and touch can be both active at the same time.
2220 */
2221TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
2222 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2223 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002224 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2225 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002226 window->setFrame(Rect(0, 0, 200, 200));
2227
2228 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2229
2230 constexpr int32_t touchDeviceId = 4;
2231 constexpr int32_t stylusDeviceId = 2;
2232
2233 // Stylus down on the window
2234 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2235 .deviceId(stylusDeviceId)
2236 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2237 .build());
2238 window->consumeMotionEvent(
2239 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2240
2241 // Touch down on window
2242 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2243 .deviceId(touchDeviceId)
2244 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2245 .build());
2246 // Touch move on window
2247 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2248 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2249 .deviceId(touchDeviceId)
2250 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2251 .build());
2252 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2253
2254 // Subsequent stylus movements are delivered correctly
2255 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2256 .deviceId(stylusDeviceId)
2257 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2258 .build());
2259 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2260 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2261
2262 // and subsequent touches continue to work
2263 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2264 .deviceId(touchDeviceId)
2265 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2266 .build());
2267 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2268 window->assertNoEvents();
2269}
2270
2271/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002272 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002273 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002274 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002275TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002276 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002277 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002278 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2279 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002280 window->setFrame(Rect(0, 0, 200, 200));
2281
2282 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2283
2284 constexpr int32_t touchDeviceId = 4;
2285 constexpr int32_t stylusDeviceId = 2;
2286
2287 // Touch down on window
2288 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2289 .deviceId(touchDeviceId)
2290 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2291 .build());
2292 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2293 .deviceId(touchDeviceId)
2294 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2295 .build());
2296 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2297 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2298
2299 // Stylus hover on the window
2300 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2301 .deviceId(stylusDeviceId)
2302 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2303 .build());
2304 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2305 .deviceId(stylusDeviceId)
2306 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2307 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002308 // Stylus hover movement causes touch to be canceled
2309 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2310 WithCoords(141, 146)));
2311 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2312 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2313 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2314 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002315
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002316 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002317 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2318 .deviceId(touchDeviceId)
2319 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2320 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002321
2322 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002323}
2324
2325/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002326 * One window. Touch down on the window. Then, stylus hover on the window from another device.
2327 * Ensure that touch is not canceled, because stylus hover can be active at the same time as touch.
2328 */
2329TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2330 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2331 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002332 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2333 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002334 window->setFrame(Rect(0, 0, 200, 200));
2335
2336 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2337
2338 constexpr int32_t touchDeviceId = 4;
2339 constexpr int32_t stylusDeviceId = 2;
2340
2341 // Touch down on window
2342 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2343 .deviceId(touchDeviceId)
2344 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2345 .build());
2346 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2347 .deviceId(touchDeviceId)
2348 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2349 .build());
2350 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2351 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2352
2353 // Stylus hover on the window
2354 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2355 .deviceId(stylusDeviceId)
2356 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2357 .build());
2358 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2359 .deviceId(stylusDeviceId)
2360 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2361 .build());
2362 // Stylus hover movement is received normally
2363 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2364 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2365 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2366 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2367
2368 // Subsequent touch movements also work
2369 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2370 .deviceId(touchDeviceId)
2371 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2372 .build());
2373 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2374 WithCoords(142, 147)));
2375
2376 window->assertNoEvents();
2377}
2378
2379/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002380 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2381 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2382 * become active.
2383 */
2384TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002385 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002386 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002387 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2388 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002389 window->setFrame(Rect(0, 0, 200, 200));
2390
2391 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2392
2393 constexpr int32_t stylusDeviceId1 = 3;
2394 constexpr int32_t stylusDeviceId2 = 5;
2395
2396 // Touch down on window
2397 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2398 .deviceId(stylusDeviceId1)
2399 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2400 .build());
2401 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2402 .deviceId(stylusDeviceId1)
2403 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2404 .build());
2405 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2406 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2407
2408 // Second stylus down
2409 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2410 .deviceId(stylusDeviceId2)
2411 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2412 .build());
2413 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2414 .deviceId(stylusDeviceId2)
2415 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2416 .build());
2417
2418 // First stylus is canceled, second one takes over.
2419 window->consumeMotionEvent(
2420 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2421 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2422 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2423
2424 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2425 .deviceId(stylusDeviceId1)
2426 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2427 .build());
2428 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002429 window->assertNoEvents();
2430}
2431
2432/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002433 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2434 * both stylus devices can function simultaneously.
2435 */
2436TEST_F(InputDispatcherMultiDeviceTest, TwoStylusDevicesActiveAtTheSameTime) {
2437 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2438 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002439 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2440 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002441 window->setFrame(Rect(0, 0, 200, 200));
2442
2443 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2444
2445 constexpr int32_t stylusDeviceId1 = 3;
2446 constexpr int32_t stylusDeviceId2 = 5;
2447
2448 // Touch down on window
2449 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2450 .deviceId(stylusDeviceId1)
2451 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2452 .build());
2453 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2454 .deviceId(stylusDeviceId1)
2455 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2456 .build());
2457 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2458 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2459
2460 // Second stylus down
2461 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2462 .deviceId(stylusDeviceId2)
2463 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2464 .build());
2465 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2466 .deviceId(stylusDeviceId2)
2467 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2468 .build());
2469 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2470 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2471
2472 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2473 .deviceId(stylusDeviceId1)
2474 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2475 .build());
2476 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2477 window->assertNoEvents();
2478}
2479
2480/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002481 * One window. Touch down on the window. Then, stylus down on the window from another device.
2482 * Ensure that is canceled, because stylus down should be preferred over touch.
2483 */
2484TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002485 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002486 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002487 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2488 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002489 window->setFrame(Rect(0, 0, 200, 200));
2490
2491 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2492
2493 constexpr int32_t touchDeviceId = 4;
2494 constexpr int32_t stylusDeviceId = 2;
2495
2496 // Touch down on window
2497 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2498 .deviceId(touchDeviceId)
2499 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2500 .build());
2501 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2502 .deviceId(touchDeviceId)
2503 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2504 .build());
2505 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2506 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2507
2508 // Stylus down on the window
2509 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2510 .deviceId(stylusDeviceId)
2511 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2512 .build());
2513 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2514 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2515
2516 // Subsequent stylus movements are delivered correctly
2517 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2518 .deviceId(stylusDeviceId)
2519 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2520 .build());
2521 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2522 WithCoords(101, 111)));
2523}
2524
2525/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002526 * One window. Touch down on the window. Then, stylus down on the window from another device.
2527 * Ensure that both touch and stylus are functioning independently.
2528 */
2529TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusDown) {
2530 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2531 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002532 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2533 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002534 window->setFrame(Rect(0, 0, 200, 200));
2535
2536 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2537
2538 constexpr int32_t touchDeviceId = 4;
2539 constexpr int32_t stylusDeviceId = 2;
2540
2541 // Touch down on window
2542 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2543 .deviceId(touchDeviceId)
2544 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2545 .build());
2546 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2547 .deviceId(touchDeviceId)
2548 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2549 .build());
2550 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2551 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2552
2553 // Stylus down on the window
2554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2555 .deviceId(stylusDeviceId)
2556 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2557 .build());
2558 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2559
2560 // Subsequent stylus movements are delivered correctly
2561 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2562 .deviceId(stylusDeviceId)
2563 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2564 .build());
2565 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2566 WithCoords(101, 111)));
2567
2568 // Touch continues to work too
2569 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2570 .deviceId(touchDeviceId)
2571 .pointer(PointerBuilder(0, ToolType::FINGER).x(148).y(149))
2572 .build());
2573 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2574}
2575
2576/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002577 * Two windows: a window on the left and a window on the right.
2578 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2579 * down. Then, on the left window, also place second touch pointer down.
2580 * This test tries to reproduce a crash.
2581 * In the buggy implementation, second pointer down on the left window would cause a crash.
2582 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002583TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch_legacy) {
2584 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002585 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002586 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2587 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002588 leftWindow->setFrame(Rect(0, 0, 200, 200));
2589
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002590 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2591 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002592 rightWindow->setFrame(Rect(200, 0, 400, 200));
2593
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002594 mDispatcher->onWindowInfosChanged(
2595 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002596
2597 const int32_t touchDeviceId = 4;
2598 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002599
2600 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002601 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2602 .deviceId(mouseDeviceId)
2603 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2604 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002605 leftWindow->consumeMotionEvent(
2606 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2607
2608 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002609 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2610 .deviceId(mouseDeviceId)
2611 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2612 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2613 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002614
2615 leftWindow->consumeMotionEvent(
2616 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2617 leftWindow->consumeMotionEvent(
2618 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2619
Prabir Pradhan678438e2023-04-13 19:32:51 +00002620 mDispatcher->notifyMotion(
2621 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2622 .deviceId(mouseDeviceId)
2623 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2624 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2625 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2626 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002627 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2628
2629 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002630 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2631 .deviceId(touchDeviceId)
2632 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2633 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002634 leftWindow->assertNoEvents();
2635
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002636 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2637
2638 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002639 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2640 .deviceId(touchDeviceId)
2641 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2642 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2643 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002644 // Since this is now a new splittable pointer going down on the left window, and it's coming
2645 // from a different device, the current gesture in the left window (pointer down) should first
2646 // be canceled.
2647 leftWindow->consumeMotionEvent(
2648 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002649 leftWindow->consumeMotionEvent(
2650 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2651 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2652 // current implementation.
2653 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2654 rightWindow->consumeMotionEvent(
2655 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2656
2657 leftWindow->assertNoEvents();
2658 rightWindow->assertNoEvents();
2659}
2660
2661/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002662 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002663 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2664 * down. Then, on the left window, also place second touch pointer down.
2665 * This test tries to reproduce a crash.
2666 * In the buggy implementation, second pointer down on the left window would cause a crash.
2667 */
2668TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
2669 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2670 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002671 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2672 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002673 leftWindow->setFrame(Rect(0, 0, 200, 200));
2674
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002675 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2676 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002677 rightWindow->setFrame(Rect(200, 0, 400, 200));
2678
2679 mDispatcher->onWindowInfosChanged(
2680 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2681
2682 const int32_t touchDeviceId = 4;
2683 const int32_t mouseDeviceId = 6;
2684
2685 // Start hovering over the left window
2686 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2687 .deviceId(mouseDeviceId)
2688 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2689 .build());
2690 leftWindow->consumeMotionEvent(
2691 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2692
2693 // Mouse down on left window
2694 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2695 .deviceId(mouseDeviceId)
2696 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2697 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2698 .build());
2699
2700 leftWindow->consumeMotionEvent(
2701 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2702 leftWindow->consumeMotionEvent(
2703 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2704
2705 mDispatcher->notifyMotion(
2706 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2707 .deviceId(mouseDeviceId)
2708 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2709 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2710 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2711 .build());
2712 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2713
2714 // First touch pointer down on right window
2715 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2716 .deviceId(touchDeviceId)
2717 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2718 .build());
2719 leftWindow->assertNoEvents();
2720
2721 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2722
2723 // Second touch pointer down on left window
2724 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2725 .deviceId(touchDeviceId)
2726 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2727 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2728 .build());
2729 // Since this is now a new splittable pointer going down on the left window, and it's coming
2730 // from a different device, it will be split and delivered to left window separately.
2731 leftWindow->consumeMotionEvent(
2732 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2733 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2734 // current implementation.
2735 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2736 rightWindow->consumeMotionEvent(
2737 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2738
2739 leftWindow->assertNoEvents();
2740 rightWindow->assertNoEvents();
2741}
2742
2743/**
2744 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002745 * Mouse is hovered on the left window and stylus is hovered on the right window.
2746 */
2747TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002749 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2750 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002751 leftWindow->setFrame(Rect(0, 0, 200, 200));
2752
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002753 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2754 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002755 rightWindow->setFrame(Rect(200, 0, 400, 200));
2756
2757 mDispatcher->onWindowInfosChanged(
2758 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2759
2760 const int32_t stylusDeviceId = 3;
2761 const int32_t mouseDeviceId = 6;
2762
2763 // Start hovering over the left window
2764 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2765 .deviceId(mouseDeviceId)
2766 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2767 .build());
2768 leftWindow->consumeMotionEvent(
2769 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2770
2771 // Stylus hovered on right window
2772 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2773 .deviceId(stylusDeviceId)
2774 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2775 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002776 rightWindow->consumeMotionEvent(
2777 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2778
2779 // Subsequent HOVER_MOVE events are dispatched correctly.
2780 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2781 .deviceId(mouseDeviceId)
2782 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2783 .build());
2784 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002785 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002786
2787 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2788 .deviceId(stylusDeviceId)
2789 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2790 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002791 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002792 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002793
2794 leftWindow->assertNoEvents();
2795 rightWindow->assertNoEvents();
2796}
2797
2798/**
2799 * Three windows: a window on the left and a window on the right.
2800 * And a spy window that's positioned above all of them.
2801 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2802 * Check the stream that's received by the spy.
2803 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002804TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy_legacy) {
2805 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002806 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2807
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002808 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2809 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002810 spyWindow->setFrame(Rect(0, 0, 400, 400));
2811 spyWindow->setTrustedOverlay(true);
2812 spyWindow->setSpy(true);
2813
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002814 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2815 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002816 leftWindow->setFrame(Rect(0, 0, 200, 200));
2817
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002818 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2819 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002820
2821 rightWindow->setFrame(Rect(200, 0, 400, 200));
2822
2823 mDispatcher->onWindowInfosChanged(
2824 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2825
2826 const int32_t stylusDeviceId = 1;
2827 const int32_t touchDeviceId = 2;
2828
2829 // Stylus down on the left window
2830 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2831 .deviceId(stylusDeviceId)
2832 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2833 .build());
2834 leftWindow->consumeMotionEvent(
2835 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2836 spyWindow->consumeMotionEvent(
2837 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2838
2839 // Touch down on the right window
2840 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2841 .deviceId(touchDeviceId)
2842 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2843 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002844 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002845 rightWindow->consumeMotionEvent(
2846 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002847
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002848 // Spy window does not receive touch events, because stylus events take precedence, and it
2849 // already has an active stylus gesture.
2850
2851 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002852 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2853 .deviceId(stylusDeviceId)
2854 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2855 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002856 leftWindow->consumeMotionEvent(
2857 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2858 spyWindow->consumeMotionEvent(
2859 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002860
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002861 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002862 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2863 .deviceId(touchDeviceId)
2864 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2865 .build());
2866 rightWindow->consumeMotionEvent(
2867 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002868
2869 spyWindow->assertNoEvents();
2870 leftWindow->assertNoEvents();
2871 rightWindow->assertNoEvents();
2872}
2873
2874/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002875 * Three windows: a window on the left and a window on the right.
2876 * And a spy window that's positioned above all of them.
2877 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2878 * Check the stream that's received by the spy.
2879 */
2880TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2881 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2882 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2883
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002884 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2885 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002886 spyWindow->setFrame(Rect(0, 0, 400, 400));
2887 spyWindow->setTrustedOverlay(true);
2888 spyWindow->setSpy(true);
2889
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002890 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2891 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002892 leftWindow->setFrame(Rect(0, 0, 200, 200));
2893
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002894 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2895 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002896
2897 rightWindow->setFrame(Rect(200, 0, 400, 200));
2898
2899 mDispatcher->onWindowInfosChanged(
2900 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2901
2902 const int32_t stylusDeviceId = 1;
2903 const int32_t touchDeviceId = 2;
2904
2905 // Stylus down on the left window
2906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2907 .deviceId(stylusDeviceId)
2908 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2909 .build());
2910 leftWindow->consumeMotionEvent(
2911 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2912 spyWindow->consumeMotionEvent(
2913 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2914
2915 // Touch down on the right window
2916 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2917 .deviceId(touchDeviceId)
2918 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2919 .build());
2920 leftWindow->assertNoEvents();
2921 rightWindow->consumeMotionEvent(
2922 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2923 spyWindow->consumeMotionEvent(
2924 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2925
2926 // Stylus movements continue. They should be delivered to the left window and to the spy window
2927 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2928 .deviceId(stylusDeviceId)
2929 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2930 .build());
2931 leftWindow->consumeMotionEvent(
2932 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2933 spyWindow->consumeMotionEvent(
2934 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2935
2936 // Further touch MOVE events keep going to the right window and to the spy
2937 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2938 .deviceId(touchDeviceId)
2939 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2940 .build());
2941 rightWindow->consumeMotionEvent(
2942 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2943 spyWindow->consumeMotionEvent(
2944 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2945
2946 spyWindow->assertNoEvents();
2947 leftWindow->assertNoEvents();
2948 rightWindow->assertNoEvents();
2949}
2950
2951/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002952 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2953 * both.
2954 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002955 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002956 * At the same time, left and right should be getting independent streams of hovering and touch,
2957 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002958 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002959TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002960 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002961 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2962
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002963 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2964 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002965 spyWindow->setFrame(Rect(0, 0, 400, 400));
2966 spyWindow->setTrustedOverlay(true);
2967 spyWindow->setSpy(true);
2968
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002969 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2970 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002971 leftWindow->setFrame(Rect(0, 0, 200, 200));
2972
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002973 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2974 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002975 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 hover on the left window
2984 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, 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_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2990 spyWindow->consumeMotionEvent(
2991 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2992
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002993 // Touch down on the right window. Spy doesn't receive this touch because it already has
2994 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002995 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2996 .deviceId(touchDeviceId)
2997 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2998 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002999 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003000 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003001 rightWindow->consumeMotionEvent(
3002 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3003
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003004 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003005 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3006 .deviceId(stylusDeviceId)
3007 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3008 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003009 leftWindow->consumeMotionEvent(
3010 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003011 spyWindow->consumeMotionEvent(
3012 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003013
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003014 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003015 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3016 .deviceId(touchDeviceId)
3017 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3018 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003019 rightWindow->consumeMotionEvent(
3020 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3021
3022 spyWindow->assertNoEvents();
3023 leftWindow->assertNoEvents();
3024 rightWindow->assertNoEvents();
3025}
3026
3027/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003028 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3029 * both.
3030 * Check hover in left window and touch down in the right window.
3031 * At first, spy should receive hover. Next, spy should receive touch.
3032 * At the same time, left and right should be getting independent streams of hovering and touch,
3033 * respectively.
3034 */
3035TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverDoesNotBlockTouchWithSpy) {
3036 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3037 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3038
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003039 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3040 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003041 spyWindow->setFrame(Rect(0, 0, 400, 400));
3042 spyWindow->setTrustedOverlay(true);
3043 spyWindow->setSpy(true);
3044
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003045 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3046 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003047 leftWindow->setFrame(Rect(0, 0, 200, 200));
3048
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003049 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3050 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003051 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
3069 // Touch down on the right window.
3070 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3071 .deviceId(touchDeviceId)
3072 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3073 .build());
3074 leftWindow->assertNoEvents();
3075 spyWindow->consumeMotionEvent(
3076 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3077 rightWindow->consumeMotionEvent(
3078 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3079
3080 // Stylus movements continue. They should be delivered to the left window and the spy.
3081 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3082 .deviceId(stylusDeviceId)
3083 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3084 .build());
3085 leftWindow->consumeMotionEvent(
3086 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3087 spyWindow->consumeMotionEvent(
3088 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3089
3090 // Touch movements continue. They should be delivered to the right window and the spy
3091 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3092 .deviceId(touchDeviceId)
3093 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3094 .build());
3095 rightWindow->consumeMotionEvent(
3096 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3097 spyWindow->consumeMotionEvent(
3098 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3099
3100 spyWindow->assertNoEvents();
3101 leftWindow->assertNoEvents();
3102 rightWindow->assertNoEvents();
3103}
3104
3105/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003106 * On a single window, use two different devices: mouse and touch.
3107 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3108 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3109 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3110 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3111 * represent a new gesture.
3112 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003113TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown_legacy) {
3114 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003115 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003116 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3117 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003118 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 Vishniakoued89cbb2023-10-13 10:42:44 -07003187 * On a single window, use two different devices: mouse and touch.
3188 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3189 * Mouse is clicked next, which should not interfere with the touch stream.
3190 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is also
3191 * delivered correctly.
3192 */
3193TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
3194 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3195 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003196 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3197 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003198 window->setFrame(Rect(0, 0, 400, 400));
3199
3200 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3201
3202 const int32_t touchDeviceId = 4;
3203 const int32_t mouseDeviceId = 6;
3204
3205 // First touch pointer down
3206 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3207 .deviceId(touchDeviceId)
3208 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3209 .build());
3210 // Second touch pointer down
3211 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3212 .deviceId(touchDeviceId)
3213 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3214 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3215 .build());
3216 // First touch pointer lifts. The second one remains down
3217 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3218 .deviceId(touchDeviceId)
3219 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3220 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3221 .build());
3222 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3223 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3224 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3225
3226 // Mouse down
3227 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3228 .deviceId(mouseDeviceId)
3229 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3230 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3231 .build());
3232
3233 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3234
3235 mDispatcher->notifyMotion(
3236 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3237 .deviceId(mouseDeviceId)
3238 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3239 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3240 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3241 .build());
3242 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3243
3244 // Second touch pointer down.
3245 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3246 .deviceId(touchDeviceId)
3247 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3248 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3249 .build());
3250 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_0_DOWN), WithDeviceId(touchDeviceId),
3251 WithPointerCount(2u)));
3252
3253 // Mouse movements should continue to work
3254 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3255 .deviceId(mouseDeviceId)
3256 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3257 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3258 .build());
3259 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3260
3261 window->assertNoEvents();
3262}
3263
3264/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003265 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3266 * the injected event.
3267 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003268TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent_legacy) {
3269 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003270 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003271 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3272 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003273 window->setFrame(Rect(0, 0, 400, 400));
3274
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003275 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003276
3277 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003278 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3279 // completion.
3280 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003281 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003282 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3283 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003284 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003285 .build()));
3286 window->consumeMotionEvent(
3287 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3288
3289 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3290 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003291 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3292 .deviceId(touchDeviceId)
3293 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3294 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003295
3296 window->consumeMotionEvent(
3297 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3298 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3299}
3300
3301/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003302 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event runs
3303 * parallel to the injected event.
3304 */
3305TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
3306 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3307 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003308 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3309 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003310 window->setFrame(Rect(0, 0, 400, 400));
3311
3312 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3313
3314 const int32_t touchDeviceId = 4;
3315 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3316 // completion.
3317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3318 injectMotionEvent(*mDispatcher,
3319 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3320 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
3321 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3322 .build()));
3323 window->consumeMotionEvent(
3324 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3325
3326 // Now a real touch comes. The injected pointer will remain, and the new gesture will also be
3327 // allowed through.
3328 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3329 .deviceId(touchDeviceId)
3330 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3331 .build());
3332 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3333}
3334
3335/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003336 * This test is similar to the test above, but the sequence of injected events is different.
3337 *
3338 * Two windows: a window on the left and a window on the right.
3339 * Mouse is hovered over the left window.
3340 * Next, we tap on the left window, where the cursor was last seen.
3341 *
3342 * After that, we inject one finger down onto the right window, and then a second finger down onto
3343 * the left window.
3344 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3345 * window (first), and then another on the left window (second).
3346 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3347 * In the buggy implementation, second finger down on the left window would cause a crash.
3348 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003349TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch_legacy) {
3350 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003351 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003352 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3353 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003354 leftWindow->setFrame(Rect(0, 0, 200, 200));
3355
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003356 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3357 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003358 rightWindow->setFrame(Rect(200, 0, 400, 200));
3359
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003360 mDispatcher->onWindowInfosChanged(
3361 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003362
3363 const int32_t mouseDeviceId = 6;
3364 const int32_t touchDeviceId = 4;
3365 // Hover over the left window. Keep the cursor there.
3366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003367 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003368 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3369 AINPUT_SOURCE_MOUSE)
3370 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003371 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003372 .build()));
3373 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3374
3375 // Tap on left window
3376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003377 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003378 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3379 AINPUT_SOURCE_TOUCHSCREEN)
3380 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003381 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003382 .build()));
3383
3384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003385 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003386 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3387 AINPUT_SOURCE_TOUCHSCREEN)
3388 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003389 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003390 .build()));
3391 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3392 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3393 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3394
3395 // First finger down on right window
3396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003397 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003398 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3399 AINPUT_SOURCE_TOUCHSCREEN)
3400 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003401 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003402 .build()));
3403 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3404
3405 // Second finger down on the left window
3406 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003407 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003408 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3409 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003410 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3411 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003412 .build()));
3413 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3414 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3415
3416 // No more events
3417 leftWindow->assertNoEvents();
3418 rightWindow->assertNoEvents();
3419}
3420
3421/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003422 * This test is similar to the test above, but the sequence of injected events is different.
3423 *
3424 * Two windows: a window on the left and a window on the right.
3425 * Mouse is hovered over the left window.
3426 * Next, we tap on the left window, where the cursor was last seen.
3427 *
3428 * After that, we send one finger down onto the right window, and then a second finger down onto
3429 * the left window.
3430 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3431 * window (first), and then another on the left window (second).
3432 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3433 * In the buggy implementation, second finger down on the left window would cause a crash.
3434 */
3435TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
3436 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3437 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003438 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3439 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003440 leftWindow->setFrame(Rect(0, 0, 200, 200));
3441
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003442 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3443 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003444 rightWindow->setFrame(Rect(200, 0, 400, 200));
3445
3446 mDispatcher->onWindowInfosChanged(
3447 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3448
3449 const int32_t mouseDeviceId = 6;
3450 const int32_t touchDeviceId = 4;
3451 // Hover over the left window. Keep the cursor there.
3452 mDispatcher->notifyMotion(
3453 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3454 .deviceId(mouseDeviceId)
3455 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3456 .build());
3457 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3458
3459 // Tap on left window
3460 mDispatcher->notifyMotion(
3461 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3462 .deviceId(touchDeviceId)
3463 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3464 .build());
3465
3466 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3467 .deviceId(touchDeviceId)
3468 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3469 .build());
3470 leftWindow->consumeMotionEvent(
3471 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithDeviceId(touchDeviceId)));
3472 leftWindow->consumeMotionEvent(
3473 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithDeviceId(touchDeviceId)));
3474
3475 // First finger down on right window
3476 mDispatcher->notifyMotion(
3477 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3478 .deviceId(touchDeviceId)
3479 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3480 .build());
3481 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3482
3483 // Second finger down on the left window
3484 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3485 .deviceId(touchDeviceId)
3486 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3487 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
3488 .build());
3489 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3490 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3491
3492 // No more events
3493 leftWindow->assertNoEvents();
3494 rightWindow->assertNoEvents();
3495}
3496
3497/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003498 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3499 * While the touch is down, new hover events from the stylus device should be ignored. After the
3500 * touch is gone, stylus hovering should start working again.
3501 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003502TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003503 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003504 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003505 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3506 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003507 window->setFrame(Rect(0, 0, 200, 200));
3508
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003509 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003510
3511 const int32_t stylusDeviceId = 5;
3512 const int32_t touchDeviceId = 4;
3513 // Start hovering with stylus
3514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003515 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003516 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003517 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003518 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003519 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003520 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003521
3522 // Finger down on the window
3523 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003524 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003525 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003526 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003527 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003528 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003529 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003530
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003531 // Continue hovering with stylus.
3532 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003533 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003534 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3535 AINPUT_SOURCE_STYLUS)
3536 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003537 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003538 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003539 // Hovers continue to work
3540 window->consumeMotionEvent(
3541 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003542
3543 // Lift up the finger
3544 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003545 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003546 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3547 AINPUT_SOURCE_TOUCHSCREEN)
3548 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003549 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003550 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003551
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003553 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003554 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3555 AINPUT_SOURCE_STYLUS)
3556 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003557 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003558 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003559 window->consumeMotionEvent(
3560 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003561 window->assertNoEvents();
3562}
3563
3564/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003565 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3566 * While the touch is down, hovering from the stylus is not affected. After the touch is gone,
3567 * check that the stylus hovering continues to work.
3568 */
3569TEST_F(InputDispatcherMultiDeviceTest, StylusHoverWithTouchTap) {
3570 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3571 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003572 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3573 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003574 window->setFrame(Rect(0, 0, 200, 200));
3575
3576 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3577
3578 const int32_t stylusDeviceId = 5;
3579 const int32_t touchDeviceId = 4;
3580 // Start hovering with stylus
3581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3582 .deviceId(stylusDeviceId)
3583 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3584 .build());
3585 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3586
3587 // Finger down on the window
3588 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3589 .deviceId(touchDeviceId)
3590 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3591 .build());
3592 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3593
3594 // Continue hovering with stylus.
3595 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3596 .deviceId(stylusDeviceId)
3597 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
3598 .build());
3599 // Hovers continue to work
3600 window->consumeMotionEvent(
3601 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3602
3603 // Lift up the finger
3604 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3605 .deviceId(touchDeviceId)
3606 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3607 .build());
3608 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
3609
3610 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3611 .deviceId(stylusDeviceId)
3612 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
3613 .build());
3614 window->consumeMotionEvent(
3615 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3616 window->assertNoEvents();
3617}
3618
3619/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003620 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3621 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3622 *
3623 * Two windows: one on the left and one on the right.
3624 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3625 * Stylus down on the left window, and then touch down on the right window.
3626 * Check that the right window doesn't get touches while the stylus is down on the left window.
3627 */
3628TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3629 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3630 sp<FakeWindowHandle> leftWindow =
3631 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003632 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003633 leftWindow->setFrame(Rect(0, 0, 100, 100));
3634
3635 sp<FakeWindowHandle> sbtRightWindow =
3636 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003637 "Stylus blocks touch (right) window",
3638 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003639 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3640 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3641
3642 mDispatcher->onWindowInfosChanged(
3643 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3644
3645 const int32_t stylusDeviceId = 5;
3646 const int32_t touchDeviceId = 4;
3647
3648 // Stylus down in the left window
3649 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3650 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3651 .deviceId(stylusDeviceId)
3652 .build());
3653 leftWindow->consumeMotionEvent(
3654 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3655
3656 // Finger tap on the right window
3657 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3658 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3659 .deviceId(touchDeviceId)
3660 .build());
3661 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3662 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3663 .deviceId(touchDeviceId)
3664 .build());
3665
3666 // The touch should be blocked, because stylus is down somewhere else on screen!
3667 sbtRightWindow->assertNoEvents();
3668
3669 // Continue stylus motion, and ensure it's not impacted.
3670 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3671 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3672 .deviceId(stylusDeviceId)
3673 .build());
3674 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3675 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3676 .deviceId(stylusDeviceId)
3677 .build());
3678 leftWindow->consumeMotionEvent(
3679 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3680 leftWindow->consumeMotionEvent(
3681 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3682
3683 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3684 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3685 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3686 .deviceId(touchDeviceId)
3687 .build());
3688 sbtRightWindow->consumeMotionEvent(
3689 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3690}
3691
3692/**
3693 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3694 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3695 *
3696 * Two windows: one on the left and one on the right.
3697 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3698 * Stylus hover on the left window, and then touch down on the right window.
3699 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3700 */
3701TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3703 sp<FakeWindowHandle> leftWindow =
3704 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003705 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003706 leftWindow->setFrame(Rect(0, 0, 100, 100));
3707
3708 sp<FakeWindowHandle> sbtRightWindow =
3709 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003710 "Stylus blocks touch (right) window",
3711 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003712 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3713 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3714
3715 mDispatcher->onWindowInfosChanged(
3716 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3717
3718 const int32_t stylusDeviceId = 5;
3719 const int32_t touchDeviceId = 4;
3720
3721 // Stylus hover in the left window
3722 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3723 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3724 .deviceId(stylusDeviceId)
3725 .build());
3726 leftWindow->consumeMotionEvent(
3727 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3728
3729 // Finger tap on the right window
3730 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3731 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3732 .deviceId(touchDeviceId)
3733 .build());
3734 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3735 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3736 .deviceId(touchDeviceId)
3737 .build());
3738
3739 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3740 sbtRightWindow->assertNoEvents();
3741
3742 // Continue stylus motion, and ensure it's not impacted.
3743 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3744 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3745 .deviceId(stylusDeviceId)
3746 .build());
3747 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3748 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3749 .deviceId(stylusDeviceId)
3750 .build());
3751 leftWindow->consumeMotionEvent(
3752 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3753 leftWindow->consumeMotionEvent(
3754 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3755
3756 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3758 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3759 .deviceId(touchDeviceId)
3760 .build());
3761 sbtRightWindow->consumeMotionEvent(
3762 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3763}
3764
3765/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003766 * A spy window above a window with no input channel.
3767 * Start hovering with a stylus device, and then tap with it.
3768 * Ensure spy window receives the entire sequence.
3769 */
3770TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3771 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003772 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3773 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003774 spyWindow->setFrame(Rect(0, 0, 200, 200));
3775 spyWindow->setTrustedOverlay(true);
3776 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003777 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3778 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003779 window->setNoInputChannel(true);
3780 window->setFrame(Rect(0, 0, 200, 200));
3781
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003782 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003783
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003784 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3786 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3787 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003788 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3789 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003790 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3791 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3792 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003793 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3794
3795 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003796 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3797 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3798 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003799 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3800
3801 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003802 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3803 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3804 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003805 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3806
3807 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003808 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3809 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3810 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003811 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3812 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003813 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3814 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3815 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003816 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3817
3818 // No more events
3819 spyWindow->assertNoEvents();
3820 window->assertNoEvents();
3821}
3822
3823/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003824 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3825 * rejected. But since we already have an ongoing gesture, this event should be processed.
3826 * This prevents inconsistent events being handled inside the dispatcher.
3827 */
3828TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3829 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3830
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003831 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3832 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003833 window->setFrame(Rect(0, 0, 200, 200));
3834
3835 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3836
3837 // Start hovering with stylus
3838 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3839 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3840 .build());
3841 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3842
3843 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3844 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3845 .build();
3846 // Make this 'hoverExit' event stale
3847 mFakePolicy->setStaleEventTimeout(100ms);
3848 std::this_thread::sleep_for(100ms);
3849
3850 // It shouldn't be dropped by the dispatcher, even though it's stale.
3851 mDispatcher->notifyMotion(hoverExit);
3852 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3853
3854 // Stylus starts hovering again! There should be no crash.
3855 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3856 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3857 .build());
3858 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3859}
3860
3861/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003862 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3863 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3864 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3865 * While the mouse is down, new move events from the touch device should be ignored.
3866 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003867TEST_F(InputDispatcherTest, TouchPilferAndMouseMove_legacy) {
3868 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003869 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003870 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3871 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003872 spyWindow->setFrame(Rect(0, 0, 200, 200));
3873 spyWindow->setTrustedOverlay(true);
3874 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003875 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3876 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003877 window->setFrame(Rect(0, 0, 200, 200));
3878
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003879 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003880
3881 const int32_t mouseDeviceId = 7;
3882 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003883
3884 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003885 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3886 .deviceId(mouseDeviceId)
3887 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3888 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003889 spyWindow->consumeMotionEvent(
3890 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3891 window->consumeMotionEvent(
3892 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3893
3894 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003895 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3896 .deviceId(touchDeviceId)
3897 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3898 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003899 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3900 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3901 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3902 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3903
Prabir Pradhan678438e2023-04-13 19:32:51 +00003904 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3905 .deviceId(touchDeviceId)
3906 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3907 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003908 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3909 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3910
3911 // Pilfer the stream
3912 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3913 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3914
Prabir Pradhan678438e2023-04-13 19:32:51 +00003915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3916 .deviceId(touchDeviceId)
3917 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3918 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003919 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3920
3921 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003922 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3923 .deviceId(mouseDeviceId)
3924 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3925 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3926 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003927
3928 spyWindow->consumeMotionEvent(
3929 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3930 spyWindow->consumeMotionEvent(
3931 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3932 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3933
Prabir Pradhan678438e2023-04-13 19:32:51 +00003934 mDispatcher->notifyMotion(
3935 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3936 .deviceId(mouseDeviceId)
3937 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3938 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3939 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3940 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003941 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3942 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3943
3944 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003945 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3946 .deviceId(mouseDeviceId)
3947 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3948 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3949 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003950 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3951 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3952
3953 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003954 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3955 .deviceId(touchDeviceId)
3956 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3957 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003958
3959 // No more events
3960 spyWindow->assertNoEvents();
3961 window->assertNoEvents();
3962}
3963
3964/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003965 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3966 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3967 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3968 * While the mouse is down, new move events from the touch device should continue to work.
3969 */
3970TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3971 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3972 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003973 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3974 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003975 spyWindow->setFrame(Rect(0, 0, 200, 200));
3976 spyWindow->setTrustedOverlay(true);
3977 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003978 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3979 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003980 window->setFrame(Rect(0, 0, 200, 200));
3981
3982 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
3983
3984 const int32_t mouseDeviceId = 7;
3985 const int32_t touchDeviceId = 4;
3986
3987 // Hover a bit with mouse first
3988 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3989 .deviceId(mouseDeviceId)
3990 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3991 .build());
3992 spyWindow->consumeMotionEvent(
3993 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3994 window->consumeMotionEvent(
3995 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3996
3997 // Start touching
3998 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3999 .deviceId(touchDeviceId)
4000 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4001 .build());
4002
4003 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4004 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4005
4006 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4007 .deviceId(touchDeviceId)
4008 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
4009 .build());
4010 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4011 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4012
4013 // Pilfer the stream
4014 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4015 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
4016 // Hover is not pilfered! Only touch.
4017
4018 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4019 .deviceId(touchDeviceId)
4020 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
4021 .build());
4022 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4023
4024 // Mouse down
4025 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4026 .deviceId(mouseDeviceId)
4027 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4028 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4029 .build());
4030
4031 spyWindow->consumeMotionEvent(
4032 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4033 spyWindow->consumeMotionEvent(
4034 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4035 window->consumeMotionEvent(
4036 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4037 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4038
4039 mDispatcher->notifyMotion(
4040 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4041 .deviceId(mouseDeviceId)
4042 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4043 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4044 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4045 .build());
4046 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4047 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4048
4049 // Mouse move!
4050 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4051 .deviceId(mouseDeviceId)
4052 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4053 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4054 .build());
4055 spyWindow->consumeMotionEvent(
4056 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4057 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4058
4059 // Touch move!
4060 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4061 .deviceId(touchDeviceId)
4062 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4063 .build());
4064 spyWindow->consumeMotionEvent(
4065 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4066
4067 // No more events
4068 spyWindow->assertNoEvents();
4069 window->assertNoEvents();
4070}
4071
4072/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004073 * On the display, have a single window, and also an area where there's no window.
4074 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
4075 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
4076 */
4077TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
4078 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4079 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004080 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004081
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004082 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004083
4084 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00004085 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004086
4087 mDispatcher->waitForIdle();
4088 window->assertNoEvents();
4089
4090 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004091 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004092 mDispatcher->waitForIdle();
4093 window->consumeMotionDown();
4094}
4095
4096/**
4097 * Same test as above, but instead of touching the empty space, the first touch goes to
4098 * non-touchable window.
4099 */
4100TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
4101 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4102 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004103 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004104 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4105 window1->setTouchable(false);
4106 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004107 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004108 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4109
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004110 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004111
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004112 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004113 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004114
4115 mDispatcher->waitForIdle();
4116 window1->assertNoEvents();
4117 window2->assertNoEvents();
4118
4119 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004120 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004121 mDispatcher->waitForIdle();
4122 window2->consumeMotionDown();
4123}
4124
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004125/**
4126 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
4127 * to the event time of the first ACTION_DOWN sent to the particular window.
4128 */
4129TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
4130 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4131 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004132 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004133 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4134 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004135 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004136 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4137
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004138 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004139
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004140 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004141 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004142 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004143
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004144 const std::unique_ptr<MotionEvent> firstDown =
4145 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4146 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004147 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004148
4149 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004150 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004151 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004152
4153 const std::unique_ptr<MotionEvent> secondDown =
4154 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4155 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
4156 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
4157 // We currently send MOVE events to all windows receiving a split touch when there is any change
4158 // in the touch state, even when none of the pointers in the split window actually moved.
4159 // Document this behavior in the test.
4160 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004161
4162 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004163 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004164 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004165
4166 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4167 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004168
4169 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004170 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004171 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004172
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004173 window2->consumeMotionEvent(
4174 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
4175 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004176
4177 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004178 mDispatcher->notifyMotion(
4179 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004180 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004181
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004182 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
4183 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4184
4185 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004186 mDispatcher->notifyMotion(
4187 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004188 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004189
4190 window1->consumeMotionEvent(
4191 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
4192 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004193}
4194
Garfield Tandf26e862020-07-01 20:18:19 -07004195TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004196 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004197 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4198 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004199 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004200 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4201 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004202 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004203
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004204 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004205
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004206 mDispatcher->onWindowInfosChanged(
4207 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004208
4209 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004211 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004212 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4213 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004214 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004215 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004216 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004217
4218 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004220 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004221 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4222 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004223 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004224 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004225 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4226 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004227
4228 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004230 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004231 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4232 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004233 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004234 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004235 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4236 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004237
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004238 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004239 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004240 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4241 AINPUT_SOURCE_MOUSE)
4242 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4243 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004244 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004245 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004246 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004247
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004248 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004249 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004250 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4251 AINPUT_SOURCE_MOUSE)
4252 .buttonState(0)
4253 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004254 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004255 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004256 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004257
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004259 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004260 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4261 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004262 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004263 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004264 windowLeft->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004265
4266 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004268 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004269 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4270 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004271 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004272 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004273 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004274
4275 // No more events
4276 windowLeft->assertNoEvents();
4277 windowRight->assertNoEvents();
4278}
4279
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004280/**
4281 * Put two fingers down (and don't release them) and click the mouse button.
4282 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4283 * currently active gesture should be canceled, and the new one should proceed.
4284 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004285TEST_F(InputDispatcherTest, TwoPointersDownMouseClick_legacy) {
4286 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004287 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004288 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4289 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004290 window->setFrame(Rect(0, 0, 600, 800));
4291
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004292 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004293
4294 const int32_t touchDeviceId = 4;
4295 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004296
4297 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004298 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4299 .deviceId(touchDeviceId)
4300 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4301 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004302
Prabir Pradhan678438e2023-04-13 19:32:51 +00004303 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4304 .deviceId(touchDeviceId)
4305 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4306 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4307 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004308 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4309 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4310
4311 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004312 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4313 .deviceId(mouseDeviceId)
4314 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4315 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4316 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004317 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4318 WithPointerCount(2u)));
4319 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4320
Prabir Pradhan678438e2023-04-13 19:32:51 +00004321 mDispatcher->notifyMotion(
4322 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4323 .deviceId(mouseDeviceId)
4324 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4325 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4326 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4327 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004328 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4329
4330 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4331 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004332 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4333 .deviceId(touchDeviceId)
4334 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4335 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4336 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004337 window->assertNoEvents();
4338}
4339
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004340/**
4341 * Put two fingers down (and don't release them) and click the mouse button.
4342 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4343 * currently active gesture should not be canceled, and the new one should proceed in parallel.
4344 */
4345TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4346 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4347 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004348 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4349 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004350 window->setFrame(Rect(0, 0, 600, 800));
4351
4352 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4353
4354 const int32_t touchDeviceId = 4;
4355 const int32_t mouseDeviceId = 6;
4356
4357 // Two pointers down
4358 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4359 .deviceId(touchDeviceId)
4360 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4361 .build());
4362
4363 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4364 .deviceId(touchDeviceId)
4365 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4366 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4367 .build());
4368 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4369 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4370
4371 // Send a series of mouse events for a mouse click
4372 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4373 .deviceId(mouseDeviceId)
4374 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4375 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4376 .build());
4377 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4378
4379 mDispatcher->notifyMotion(
4380 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4381 .deviceId(mouseDeviceId)
4382 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4383 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4384 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4385 .build());
4386 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4387
4388 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4389 // already active gesture, it should be sent normally.
4390 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4391 .deviceId(touchDeviceId)
4392 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4393 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4394 .build());
4395 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4396 window->assertNoEvents();
4397}
4398
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004399TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4400 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4401
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004402 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4403 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004404 spyWindow->setFrame(Rect(0, 0, 600, 800));
4405 spyWindow->setTrustedOverlay(true);
4406 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004407 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4408 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004409 window->setFrame(Rect(0, 0, 600, 800));
4410
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004411 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004412 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004413
4414 // Send mouse cursor to the window
4415 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004416 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004417 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4418 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004419 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004420 .build()));
4421
4422 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4423 WithSource(AINPUT_SOURCE_MOUSE)));
4424 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4425 WithSource(AINPUT_SOURCE_MOUSE)));
4426
4427 window->assertNoEvents();
4428 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004429}
4430
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004431TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows_legacy) {
4432 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004433 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4434
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004435 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4436 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004437 spyWindow->setFrame(Rect(0, 0, 600, 800));
4438 spyWindow->setTrustedOverlay(true);
4439 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004440 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4441 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004442 window->setFrame(Rect(0, 0, 600, 800));
4443
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004444 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004445 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004446
4447 // Send mouse cursor to the window
4448 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004449 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004450 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4451 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004452 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004453 .build()));
4454
4455 // Move mouse cursor
4456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004457 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004458 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4459 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004460 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004461 .build()));
4462
4463 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4464 WithSource(AINPUT_SOURCE_MOUSE)));
4465 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4466 WithSource(AINPUT_SOURCE_MOUSE)));
4467 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4468 WithSource(AINPUT_SOURCE_MOUSE)));
4469 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4470 WithSource(AINPUT_SOURCE_MOUSE)));
4471 // Touch down on the window
4472 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004473 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004474 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4475 AINPUT_SOURCE_TOUCHSCREEN)
4476 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004477 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004478 .build()));
4479 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4480 WithSource(AINPUT_SOURCE_MOUSE)));
4481 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4482 WithSource(AINPUT_SOURCE_MOUSE)));
4483 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4484 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4485 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4486 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4487
4488 // pilfer the motion, retaining the gesture on the spy window.
4489 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4490 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4491 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4492
4493 // Touch UP on the window
4494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004495 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004496 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4497 AINPUT_SOURCE_TOUCHSCREEN)
4498 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004499 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004500 .build()));
4501 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4502 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4503
4504 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4505 // to send a new gesture. It should again go to both windows (spy and the window below), just
4506 // like the first gesture did, before pilfering. The window configuration has not changed.
4507
4508 // One more tap - DOWN
4509 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004510 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004511 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4512 AINPUT_SOURCE_TOUCHSCREEN)
4513 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004514 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004515 .build()));
4516 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4517 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4518 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4519 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4520
4521 // Touch UP on the window
4522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004523 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004524 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4525 AINPUT_SOURCE_TOUCHSCREEN)
4526 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004527 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004528 .build()));
4529 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4530 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4531 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4532 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4533
4534 window->assertNoEvents();
4535 spyWindow->assertNoEvents();
4536}
4537
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004538TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4539 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4540 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4541
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004542 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4543 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004544 spyWindow->setFrame(Rect(0, 0, 600, 800));
4545 spyWindow->setTrustedOverlay(true);
4546 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004547 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4548 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004549 window->setFrame(Rect(0, 0, 600, 800));
4550
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004551 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004552 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4553
4554 // Send mouse cursor to the window
4555 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4556 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4557 .build());
4558
4559 // Move mouse cursor
4560 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4561 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4562 .build());
4563
4564 window->consumeMotionEvent(
4565 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4566 spyWindow->consumeMotionEvent(
4567 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4568 window->consumeMotionEvent(
4569 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4570 spyWindow->consumeMotionEvent(
4571 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4572 // Touch down on the window
4573 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4574 .deviceId(SECOND_DEVICE_ID)
4575 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4576 .build());
4577 window->consumeMotionEvent(
4578 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4579 spyWindow->consumeMotionEvent(
4580 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4581
4582 // pilfer the motion, retaining the gesture on the spy window.
4583 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4584 window->consumeMotionEvent(
4585 AllOf(WithMotionAction(ACTION_CANCEL), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4586 // Mouse hover is not pilfered
4587
4588 // Touch UP on the window
4589 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4590 .deviceId(SECOND_DEVICE_ID)
4591 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4592 .build());
4593 spyWindow->consumeMotionEvent(
4594 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4595
4596 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4597 // to send a new gesture. It should again go to both windows (spy and the window below), just
4598 // like the first gesture did, before pilfering. The window configuration has not changed.
4599
4600 // One more tap - DOWN
4601 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4602 .deviceId(SECOND_DEVICE_ID)
4603 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4604 .build());
4605 window->consumeMotionEvent(
4606 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4607 spyWindow->consumeMotionEvent(
4608 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4609
4610 // Touch UP on the window
4611 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4612 .deviceId(SECOND_DEVICE_ID)
4613 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4614 .build());
4615 window->consumeMotionEvent(
4616 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4617 spyWindow->consumeMotionEvent(
4618 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4619
4620 // Mouse movement continues normally as well
4621 // Move mouse cursor
4622 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4623 .pointer(PointerBuilder(0, ToolType::MOUSE).x(120).y(130))
4624 .build());
4625 window->consumeMotionEvent(
4626 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4627 spyWindow->consumeMotionEvent(
4628 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4629
4630 window->assertNoEvents();
4631 spyWindow->assertNoEvents();
4632}
4633
Garfield Tandf26e862020-07-01 20:18:19 -07004634// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4635// directly in this test.
4636TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004637 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004638 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4639 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004640 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004641
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004642 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004643
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004644 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004645
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004647 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004648 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4649 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004650 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004651 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004652 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004653 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004655 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004656 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4657 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004658 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004659 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004660 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4661 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004662
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004663 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004664 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004665 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4666 AINPUT_SOURCE_MOUSE)
4667 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4668 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004669 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004670 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004671 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004672
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004674 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004675 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4676 AINPUT_SOURCE_MOUSE)
4677 .buttonState(0)
4678 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004679 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004680 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004681 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004682
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004684 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004685 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4686 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004687 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004688 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004689 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004690
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004691 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4692 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4693 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004694 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004695 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4696 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004697 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004698 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004699 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004700}
4701
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004702/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004703 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4704 * is generated.
4705 */
4706TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4707 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004708 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4709 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004710 window->setFrame(Rect(0, 0, 1200, 800));
4711
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004712 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004713
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004714 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004715
4716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004717 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004718 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4719 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004720 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004721 .build()));
4722 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4723
4724 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004725 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004726 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4727}
4728
4729/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004730 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4731 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004732TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4733 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4734 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004735 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004736 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4737 ui::LogicalDisplayId::DEFAULT);
Daniel Norman7487dfa2023-08-02 16:39:45 -07004738 window->setFrame(Rect(0, 0, 1200, 800));
4739
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004740 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Daniel Norman7487dfa2023-08-02 16:39:45 -07004741
4742 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4743
4744 MotionEventBuilder hoverEnterBuilder =
4745 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4746 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4747 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4748 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4749 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4751 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4752 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4753 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4754}
4755
4756/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004757 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4758 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004759TEST_F(InputDispatcherTest, TouchDownAfterMouseHover_legacy) {
4760 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004761 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004762 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4763 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004764 window->setFrame(Rect(0, 0, 100, 100));
4765
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004766 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004767
4768 const int32_t mouseDeviceId = 7;
4769 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004770
4771 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004772 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4773 .deviceId(mouseDeviceId)
4774 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4775 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004776 window->consumeMotionEvent(
4777 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4778
4779 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004780 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4781 .deviceId(touchDeviceId)
4782 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4783 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004784
4785 window->consumeMotionEvent(
4786 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4787 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4788}
4789
4790/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004791 * If mouse is hovering when the touch goes down, the hovering should not be stopped.
4792 */
4793TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4794 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004796 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4797 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004798 window->setFrame(Rect(0, 0, 100, 100));
4799
4800 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4801
4802 const int32_t mouseDeviceId = 7;
4803 const int32_t touchDeviceId = 4;
4804
4805 // Start hovering with the mouse
4806 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4807 .deviceId(mouseDeviceId)
4808 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4809 .build());
4810 window->consumeMotionEvent(
4811 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4812
4813 // Touch goes down
4814 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4815 .deviceId(touchDeviceId)
4816 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4817 .build());
4818 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4819}
4820
4821/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004822 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004823 * The tap causes a HOVER_EXIT event to be generated because the current event
4824 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004825 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004826TEST_F(InputDispatcherTest, MouseHoverAndTouchTap_legacy) {
4827 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004828 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004829 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4830 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004831 window->setFrame(Rect(0, 0, 100, 100));
4832
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004833 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004834 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4835 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4836 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004837 ASSERT_NO_FATAL_FAILURE(
4838 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4839 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004840
4841 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004842 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4843 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4844 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004845 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004846 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4847 WithSource(AINPUT_SOURCE_MOUSE))));
4848
4849 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004850 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4851 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4852
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4854 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4855 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004856 ASSERT_NO_FATAL_FAILURE(
4857 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4858 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4859}
4860
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004861/**
4862 * Send a mouse hover event followed by a tap from touchscreen.
4863 * The tap causes a HOVER_EXIT event to be generated because the current event
4864 * stream's source has been switched.
4865 */
4866TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4867 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4868 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004869 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4870 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004871 window->setFrame(Rect(0, 0, 100, 100));
4872
4873 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4874 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4875 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4876 .build());
4877
4878 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4879 WithSource(AINPUT_SOURCE_MOUSE)));
4880
4881 // Tap on the window
4882 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4883 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4884 .build());
4885
4886 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4887 WithSource(AINPUT_SOURCE_MOUSE)));
4888
4889 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4890 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4891
4892 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4893 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4894 .build());
4895
4896 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4897 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4898}
4899
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004900TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4901 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4902 sp<FakeWindowHandle> windowDefaultDisplay =
4903 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004904 ui::LogicalDisplayId::DEFAULT);
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004905 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4906 sp<FakeWindowHandle> windowSecondDisplay =
4907 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4908 SECOND_DISPLAY_ID);
4909 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4910
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004911 mDispatcher->onWindowInfosChanged(
4912 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004913
4914 // Set cursor position in window in default display and check that hover enter and move
4915 // events are generated.
4916 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004917 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004918 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4919 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004920 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004921 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004922 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004923 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004924
4925 // Remove all windows in secondary display and check that no event happens on window in
4926 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004927 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4928
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004929 windowDefaultDisplay->assertNoEvents();
4930
4931 // Move cursor position in window in default display and check that only hover move
4932 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004933 mDispatcher->onWindowInfosChanged(
4934 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004935 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004936 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004937 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4938 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004939 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004940 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004941 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004942 windowDefaultDisplay->consumeMotionEvent(
4943 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4944 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004945 windowDefaultDisplay->assertNoEvents();
4946}
4947
Garfield Tan00f511d2019-06-12 16:55:40 -07004948TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004949 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004950
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004951 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4952 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004953 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004954 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4955 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004956 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004957
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004958 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tan00f511d2019-06-12 16:55:40 -07004959
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004960 mDispatcher->onWindowInfosChanged(
4961 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004962
4963 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4964 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004966 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004967 ui::LogicalDisplayId::DEFAULT, {610, 400}, {599, 400}));
4968 windowLeft->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004969 windowRight->assertNoEvents();
4970}
4971
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004972TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004973 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004974 sp<FakeWindowHandle> window =
4975 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
4976 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004977 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004978
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004979 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004980 setFocusedWindow(window);
4981
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004982 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004983
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004984 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004985
4986 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004987 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004988
4989 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4990 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004991 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004992 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004993}
4994
4995TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004996 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004997 sp<FakeWindowHandle> window =
4998 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
4999 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005000
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005001 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005002
Prabir Pradhan678438e2023-04-13 19:32:51 +00005003 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005004 AINPUT_SOURCE_TOUCHSCREEN,
5005 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005006
5007 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005008 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005009
5010 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
5011 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005012 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005013 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005014 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005015}
5016
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005017TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
5018 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005019 sp<FakeWindowHandle> window =
5020 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5021 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005022
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005023 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005024
5025 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5026 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
5027 .build());
5028
5029 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5030
5031 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
5032 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
5033 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5034
5035 // After the device has been reset, a new hovering stream can be sent to the window
5036 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5037 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
5038 .build());
5039 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5040}
5041
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005042TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
5043 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005044 sp<FakeWindowHandle> window =
5045 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5046 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005047 window->setFocusable(true);
5048
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005049 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005050 setFocusedWindow(window);
5051
5052 window->consumeFocusEvent(true);
5053
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005054 const NotifyKeyArgs keyArgs =
5055 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005056 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
5057 const nsecs_t injectTime = keyArgs.eventTime;
5058 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005059 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005060 // The dispatching time should be always greater than or equal to intercept key timeout.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005061 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005062 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
5063 std::chrono::nanoseconds(interceptKeyTimeout).count());
5064}
5065
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005066/**
5067 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
5068 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005069TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
5070 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005071 sp<FakeWindowHandle> window =
5072 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5073 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005074 window->setFocusable(true);
5075
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005076 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005077 setFocusedWindow(window);
5078
5079 window->consumeFocusEvent(true);
5080
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005081 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
5082 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005083
5084 // Set a value that's significantly larger than the default consumption timeout. If the
5085 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
5086 mFakePolicy->setInterceptKeyTimeout(600ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005087 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005088 // Window should receive key event immediately when same key up.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005089 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005090}
5091
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005092/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005093 * Two windows. First is a regular window. Second does not overlap with the first, and has
5094 * WATCH_OUTSIDE_TOUCH.
5095 * Both windows are owned by the same UID.
5096 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
5097 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
5098 */
5099TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
5100 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005101 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5102 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005103 window->setFrame(Rect{0, 0, 100, 100});
5104
5105 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005106 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005107 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005108 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5109 outsideWindow->setWatchOutsideTouch(true);
5110 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005111 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005112
5113 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005114 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005115 AINPUT_SOURCE_TOUCHSCREEN,
5116 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005117 window->consumeMotionDown();
5118 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
5119 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
5120 outsideWindow->consumeMotionEvent(
5121 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005122
5123 // Ensure outsideWindow doesn't get any more events for the gesture.
5124 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005125 ui::LogicalDisplayId::DEFAULT, {PointF{51, 51}}));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005126 window->consumeMotionMove();
5127 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005128}
5129
5130/**
Linnan Liccf6ce32024-04-11 20:32:13 +08005131 * Three windows:
5132 * - Left window
5133 * - Right window
5134 * - Outside window(watch for ACTION_OUTSIDE events)
5135 * The windows "left" and "outside" share the same owner, the window "right" has a different owner,
5136 * In order to allow the outside window can receive the ACTION_OUTSIDE events, the outside window is
5137 * positioned above the "left" and "right" windows, and it doesn't overlap with them.
5138 *
5139 * First, device A report a down event landed in the right window, the outside window can receive
5140 * an ACTION_OUTSIDE event that with zeroed coordinates, the device B report a down event landed
5141 * in the left window, the outside window can receive an ACTION_OUTSIDE event the with valid
5142 * coordinates, after these, device A and device B continue report MOVE event, the right and left
5143 * window can receive it, but outside window event can't receive it.
5144 */
5145TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinatesWhenMultiDevice) {
5146 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5147 sp<FakeWindowHandle> leftWindow =
5148 sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005149 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005150 leftWindow->setFrame(Rect{0, 0, 100, 100});
5151 leftWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5152
5153 sp<FakeWindowHandle> outsideWindow =
5154 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005155 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005156 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5157 outsideWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5158 outsideWindow->setWatchOutsideTouch(true);
5159
5160 std::shared_ptr<FakeApplicationHandle> anotherApplication =
5161 std::make_shared<FakeApplicationHandle>();
5162 sp<FakeWindowHandle> rightWindow =
5163 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Right Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005164 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005165 rightWindow->setFrame(Rect{100, 0, 200, 100});
5166 rightWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
5167
5168 // OutsideWindow must be above left window and right window to receive ACTION_OUTSIDE events
5169 // when left window or right window is tapped
5170 mDispatcher->onWindowInfosChanged(
5171 {{*outsideWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()},
5172 {},
5173 0,
5174 0});
5175
5176 const DeviceId deviceA = 9;
5177 const DeviceId deviceB = 3;
5178
5179 // Tap on right window use device A
5180 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5181 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5182 .deviceId(deviceA)
5183 .build());
5184 leftWindow->assertNoEvents();
5185 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5186 // Right window is belonged to another owner, so outsideWindow should receive ACTION_OUTSIDE
5187 // with zeroed coords.
5188 outsideWindow->consumeMotionEvent(
5189 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceA), WithCoords(0, 0)));
5190
5191 // Tap on left window use device B
5192 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5193 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5194 .deviceId(deviceB)
5195 .build());
5196 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5197 rightWindow->assertNoEvents();
5198 // Because new gesture down on the left window that has the same owner with outside Window, the
5199 // outside Window should receive the ACTION_OUTSIDE with coords.
5200 outsideWindow->consumeMotionEvent(
5201 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceB), WithCoords(-50, -50)));
5202
5203 // Ensure that windows that can only accept outside do not receive remaining gestures
5204 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5205 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
5206 .deviceId(deviceA)
5207 .build());
5208 leftWindow->assertNoEvents();
5209 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA)));
5210
5211 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5212 .pointer(PointerBuilder(0, ToolType::FINGER).x(51).y(51))
5213 .deviceId(deviceB)
5214 .build());
5215 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
5216 rightWindow->assertNoEvents();
5217 outsideWindow->assertNoEvents();
5218}
5219
5220/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005221 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
5222 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
5223 * ACTION_OUTSIDE event is sent per gesture.
5224 */
5225TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
5226 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
5227 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005228 sp<FakeWindowHandle> window =
5229 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5230 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005231 window->setWatchOutsideTouch(true);
5232 window->setFrame(Rect{0, 0, 100, 100});
5233 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005234 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005235 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005236 secondWindow->setFrame(Rect{100, 100, 200, 200});
5237 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005238 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005239 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005240 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005241 mDispatcher->onWindowInfosChanged(
5242 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005243
5244 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005245 mDispatcher->notifyMotion(
5246 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5247 ui::LogicalDisplayId::DEFAULT, {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005248 window->assertNoEvents();
5249 secondWindow->assertNoEvents();
5250
5251 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
5252 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005253 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005254 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005255 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005256 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
5257 window->consumeMotionEvent(
5258 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005259 secondWindow->consumeMotionDown();
5260 thirdWindow->assertNoEvents();
5261
5262 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
5263 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005264 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005265 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5266 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005267 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005268 window->assertNoEvents();
5269 secondWindow->consumeMotionMove();
5270 thirdWindow->consumeMotionDown();
5271}
5272
Prabir Pradhan814fe082022-07-22 20:22:18 +00005273TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
5274 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005275 sp<FakeWindowHandle> window =
5276 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5277 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005278 window->setFocusable(true);
5279
Patrick Williamsd828f302023-04-28 17:52:08 -05005280 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005281 setFocusedWindow(window);
5282
5283 window->consumeFocusEvent(true);
5284
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005285 const NotifyKeyArgs keyDown =
5286 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
5287 const NotifyKeyArgs keyUp =
5288 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005289 mDispatcher->notifyKey(keyDown);
5290 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005291
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005292 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5293 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005294
5295 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05005296 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005297
5298 window->consumeFocusEvent(false);
5299
Prabir Pradhan678438e2023-04-13 19:32:51 +00005300 mDispatcher->notifyKey(keyDown);
5301 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005302 window->assertNoEvents();
5303}
5304
Arthur Hung96483742022-11-15 03:30:48 +00005305TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
5306 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005307 sp<FakeWindowHandle> window =
5308 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5309 ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005310 // Ensure window is non-split and have some transform.
5311 window->setPreventSplitting(true);
5312 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05005313 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00005314
5315 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005316 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5317 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung96483742022-11-15 03:30:48 +00005318 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005319 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005320
5321 const MotionEvent secondFingerDownEvent =
5322 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005323 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung96483742022-11-15 03:30:48 +00005324 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005325 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5326 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00005327 .build();
5328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005329 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00005330 InputEventInjectionSync::WAIT_FOR_RESULT))
5331 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5332
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005333 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
5334 ASSERT_NE(nullptr, event);
5335 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
5336 EXPECT_EQ(70, event->getX(0)); // 50 + 20
5337 EXPECT_EQ(90, event->getY(0)); // 50 + 40
5338 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
5339 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00005340}
5341
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005342/**
5343 * Two windows: a splittable and a non-splittable.
5344 * The non-splittable window shouldn't receive any "incomplete" gestures.
5345 * Send the first pointer to the splittable window, and then touch the non-splittable window.
5346 * The second pointer should be dropped because the initial window is splittable, so it won't get
5347 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
5348 * "incomplete" gestures.
5349 */
5350TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
5351 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5352 sp<FakeWindowHandle> leftWindow =
5353 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005354 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005355 leftWindow->setPreventSplitting(false);
5356 leftWindow->setFrame(Rect(0, 0, 100, 100));
5357 sp<FakeWindowHandle> rightWindow =
5358 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005359 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005360 rightWindow->setPreventSplitting(true);
5361 rightWindow->setFrame(Rect(100, 100, 200, 200));
5362 mDispatcher->onWindowInfosChanged(
5363 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5364
5365 // Touch down on left, splittable window
5366 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5367 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5368 .build());
5369 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5370
5371 mDispatcher->notifyMotion(
5372 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5373 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5374 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
5375 .build());
5376 leftWindow->assertNoEvents();
5377 rightWindow->assertNoEvents();
5378}
5379
Harry Cuttsb166c002023-05-09 13:06:05 +00005380TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
5381 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005382 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5383 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005384 window->setFrame(Rect(0, 0, 400, 400));
5385 sp<FakeWindowHandle> trustedOverlay =
5386 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005387 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005388 trustedOverlay->setSpy(true);
5389 trustedOverlay->setTrustedOverlay(true);
5390
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005391 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005392
5393 // Start a three-finger touchpad swipe
5394 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5395 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5396 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5397 .build());
5398 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5399 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5400 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5401 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5402 .build());
5403 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5404 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5405 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5406 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5407 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5408 .build());
5409
5410 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5411 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5412 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
5413
5414 // Move the swipe a bit
5415 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5416 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5417 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5418 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5419 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5420 .build());
5421
5422 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5423
5424 // End the swipe
5425 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5426 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5427 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5428 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5429 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5430 .build());
5431 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5432 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5433 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5434 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5435 .build());
5436 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5437 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5438 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5439 .build());
5440
5441 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
5442 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5443 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
5444
5445 window->assertNoEvents();
5446}
5447
5448TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
5449 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005450 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5451 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005452 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005453 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005454
5455 // Start a three-finger touchpad swipe
5456 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5457 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5458 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5459 .build());
5460 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5461 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5462 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5463 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5464 .build());
5465 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5466 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5467 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5468 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5469 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5470 .build());
5471
5472 // Move the swipe a bit
5473 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5474 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5475 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5476 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5477 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5478 .build());
5479
5480 // End the swipe
5481 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5482 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5483 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5484 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5485 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5486 .build());
5487 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5488 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5489 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5490 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5491 .build());
5492 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5493 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5494 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5495 .build());
5496
5497 window->assertNoEvents();
5498}
5499
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005500/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005501 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
5502 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005503 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005504 */
5505TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
5506 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005507 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5508 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005509 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005510 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005511
5512 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
5513 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5514 .downTime(baseTime + 10)
5515 .eventTime(baseTime + 10)
5516 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5517 .build());
5518
5519 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5520
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005521 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005522 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005523
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005524 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005525
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005526 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5527 .downTime(baseTime + 10)
5528 .eventTime(baseTime + 30)
5529 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5530 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5531 .build());
5532
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005533 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5534
5535 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005536 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5537 .downTime(baseTime + 10)
5538 .eventTime(baseTime + 40)
5539 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5540 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5541 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005542
5543 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5544
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005545 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5546 .downTime(baseTime + 10)
5547 .eventTime(baseTime + 50)
5548 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5549 .build());
5550
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005551 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
5552
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005553 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5554 .downTime(baseTime + 60)
5555 .eventTime(baseTime + 60)
5556 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
5557 .build());
5558
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005559 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005560}
5561
5562/**
Hu Guo771a7692023-09-17 20:51:08 +08005563 * When there are multiple screens, such as screen projection to TV or screen recording, if the
5564 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
5565 * its coordinates should be converted by the transform of the windows of target screen.
5566 */
5567TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
5568 // This case will create a window and a spy window on the default display and mirror
5569 // window on the second display. cancel event is sent through spy window pilferPointers
5570 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5571
5572 sp<FakeWindowHandle> spyWindowDefaultDisplay =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005573 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
5574 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005575 spyWindowDefaultDisplay->setTrustedOverlay(true);
5576 spyWindowDefaultDisplay->setSpy(true);
5577
5578 sp<FakeWindowHandle> windowDefaultDisplay =
5579 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005580 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005581 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
5582
5583 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
5584 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
5585
5586 // Add the windows to the dispatcher
5587 mDispatcher->onWindowInfosChanged(
5588 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
5589 *windowSecondDisplay->getInfo()},
5590 {},
5591 0,
5592 0});
5593
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005594 // Send down to ui::LogicalDisplayId::DEFAULT
Hu Guo771a7692023-09-17 20:51:08 +08005595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005596 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5597 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Hu Guo771a7692023-09-17 20:51:08 +08005598 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5599
5600 spyWindowDefaultDisplay->consumeMotionDown();
5601 windowDefaultDisplay->consumeMotionDown();
5602
5603 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
5604
5605 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005606 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
5607 ASSERT_NE(nullptr, event);
5608 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08005609
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005610 // The cancel event is sent to windowDefaultDisplay of the ui::LogicalDisplayId::DEFAULT
5611 // display, so the coordinates of the cancel are converted by windowDefaultDisplay's transform,
5612 // the x and y coordinates are both 100, otherwise if the cancel event is sent to
5613 // windowSecondDisplay of SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005614 EXPECT_EQ(100, event->getX(0));
5615 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08005616}
5617
5618/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005619 * Ensure the correct coordinate spaces are used by InputDispatcher.
5620 *
5621 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5622 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5623 * space.
5624 */
5625class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5626public:
5627 void SetUp() override {
5628 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005629 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005630 }
5631
Linnan Li13bf76a2024-05-05 19:18:02 +08005632 void addDisplayInfo(ui::LogicalDisplayId displayId, const ui::Transform& transform) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005633 gui::DisplayInfo info;
5634 info.displayId = displayId;
5635 info.transform = transform;
5636 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005637 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005638 }
5639
5640 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5641 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005642 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005643 }
5644
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005645 void removeAllWindowsAndDisplays() {
5646 mDisplayInfos.clear();
5647 mWindowInfos.clear();
5648 }
5649
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005650 // Set up a test scenario where the display has a scaled projection and there are two windows
5651 // on the display.
5652 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5653 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5654 // respectively.
5655 ui::Transform displayTransform;
5656 displayTransform.set(2, 0, 0, 4);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005657 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005658
5659 std::shared_ptr<FakeApplicationHandle> application =
5660 std::make_shared<FakeApplicationHandle>();
5661
5662 // Add two windows to the display. Their frames are represented in the display space.
5663 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005664 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005665 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005666 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5667 addWindow(firstWindow);
5668
5669 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005670 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005671 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005672 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5673 addWindow(secondWindow);
5674 return {std::move(firstWindow), std::move(secondWindow)};
5675 }
5676
5677private:
5678 std::vector<gui::DisplayInfo> mDisplayInfos;
5679 std::vector<gui::WindowInfo> mWindowInfos;
5680};
5681
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005682TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005683 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5684 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005685 // selected so that if the hit test was performed with the point and the bounds being in
5686 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005687 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005688 AINPUT_SOURCE_TOUCHSCREEN,
5689 ui::LogicalDisplayId::DEFAULT, {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005690
5691 firstWindow->consumeMotionDown();
5692 secondWindow->assertNoEvents();
5693}
5694
5695// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5696// the event should be treated as being in the logical display space.
5697TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5698 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5699 // Send down to the first window. The point is represented in the logical display space. The
5700 // point is selected so that if the hit test was done in logical display space, then it would
5701 // end up in the incorrect window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005702 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005703 PointF{75 * 2, 55 * 4});
5704
5705 firstWindow->consumeMotionDown();
5706 secondWindow->assertNoEvents();
5707}
5708
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005709// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5710// event should be treated as being in the logical display space.
5711TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5712 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5713
5714 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5715 ui::Transform injectedEventTransform;
5716 injectedEventTransform.set(matrix);
5717 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5718 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5719
5720 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005721 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005722 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005723 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005724 .x(untransformedPoint.x)
5725 .y(untransformedPoint.y))
5726 .build();
5727 event.transform(matrix);
5728
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005729 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005730 InputEventInjectionSync::WAIT_FOR_RESULT);
5731
5732 firstWindow->consumeMotionDown();
5733 secondWindow->assertNoEvents();
5734}
5735
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005736TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5737 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5738
5739 // Send down to the second window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005740 mDispatcher->notifyMotion(
5741 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5742 ui::LogicalDisplayId::DEFAULT, {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005743
5744 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005745 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5746 ASSERT_NE(nullptr, event);
5747 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005748
5749 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005750 EXPECT_EQ(300, event->getRawX(0));
5751 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005752
5753 // Ensure that the x and y values are in the window's coordinate space.
5754 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5755 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005756 EXPECT_EQ(100, event->getX(0));
5757 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005758}
5759
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005760TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5761 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5762 // The monitor will always receive events in the logical display's coordinate space, because
5763 // it does not have a window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005764 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ui::LogicalDisplayId::DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005765
5766 // Send down to the first window.
5767 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005768 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005769 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5770 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5771
5772 // Second pointer goes down on second window.
5773 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005774 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005775 {PointF{50, 100}, PointF{150, 220}}));
5776 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5777 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5778 {1, PointF{300, 880}}};
5779 monitor.consumeMotionEvent(
5780 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5781
5782 mDispatcher->cancelCurrentTouch();
5783
5784 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5785 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5786 monitor.consumeMotionEvent(
5787 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5788}
5789
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005790TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5791 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5792
5793 // Send down to the first window.
5794 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005795 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005796 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5797
5798 // The pointer is transferred to the second window, and the second window receives it in the
5799 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005800 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005801 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5802 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5803}
5804
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005805TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5806 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5807
5808 // Send hover move to the second window, and ensure it shows up as hover enter.
5809 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005810 ui::LogicalDisplayId::DEFAULT,
5811 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005812 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5813 WithCoords(100, 80), WithRawCoords(300, 880)));
5814
5815 // Touch down at the same location and ensure a hover exit is synthesized.
5816 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005817 ui::LogicalDisplayId::DEFAULT,
5818 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005819 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5820 WithRawCoords(300, 880)));
5821 secondWindow->consumeMotionEvent(
5822 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5823 secondWindow->assertNoEvents();
5824 firstWindow->assertNoEvents();
5825}
5826
Prabir Pradhan453ae732023-10-13 14:30:14 +00005827// Same as above, but while the window is being mirrored.
5828TEST_F(InputDispatcherDisplayProjectionTest,
5829 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5830 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5831
5832 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5833 ui::Transform secondDisplayTransform;
5834 secondDisplayTransform.set(matrix);
5835 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5836
5837 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5838 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5839 addWindow(secondWindowClone);
5840
5841 // Send hover move to the second window, and ensure it shows up as hover enter.
5842 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005843 ui::LogicalDisplayId::DEFAULT,
5844 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00005845 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5846 WithCoords(100, 80), WithRawCoords(300, 880)));
5847
5848 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5849 // display.
5850 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005851 ui::LogicalDisplayId::DEFAULT,
5852 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00005853 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5854 WithRawCoords(300, 880)));
5855 secondWindow->consumeMotionEvent(
5856 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5857 secondWindow->assertNoEvents();
5858 firstWindow->assertNoEvents();
5859}
5860
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005861TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5862 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5863
5864 // Send hover enter to second window
5865 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005866 ui::LogicalDisplayId::DEFAULT,
5867 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005868 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5869 WithCoords(100, 80), WithRawCoords(300, 880)));
5870
5871 mDispatcher->cancelCurrentTouch();
5872
5873 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5874 WithRawCoords(300, 880)));
5875 secondWindow->assertNoEvents();
5876 firstWindow->assertNoEvents();
5877}
5878
Prabir Pradhan453ae732023-10-13 14:30:14 +00005879// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005880TEST_F(InputDispatcherDisplayProjectionTest,
5881 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5882 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5883
5884 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5885 ui::Transform secondDisplayTransform;
5886 secondDisplayTransform.set(matrix);
5887 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5888
5889 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5890 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5891 addWindow(secondWindowClone);
5892
5893 // Send hover enter to second window
5894 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005895 ui::LogicalDisplayId::DEFAULT,
5896 {PointF{150, 220}}));
Prabir Pradhan16463382023-10-12 23:03:19 +00005897 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5898 WithCoords(100, 80), WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005899 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00005900
5901 mDispatcher->cancelCurrentTouch();
5902
5903 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5904 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5905 WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005906 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00005907 secondWindow->assertNoEvents();
5908 firstWindow->assertNoEvents();
5909}
5910
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005911/** Ensure consistent behavior of InputDispatcher in all orientations. */
5912class InputDispatcherDisplayOrientationFixture
5913 : public InputDispatcherDisplayProjectionTest,
5914 public ::testing::WithParamInterface<ui::Rotation> {};
5915
5916// This test verifies the touchable region of a window for all rotations of the display by tapping
5917// in different locations on the display, specifically points close to the four corners of a
5918// window.
5919TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5920 constexpr static int32_t displayWidth = 400;
5921 constexpr static int32_t displayHeight = 800;
5922
5923 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5924
5925 const auto rotation = GetParam();
5926
5927 // Set up the display with the specified rotation.
5928 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5929 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5930 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5931 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5932 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005933 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005934
5935 // Create a window with its bounds determined in the logical display.
5936 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5937 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005938 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5939 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005940 window->setFrame(frameInDisplay, displayTransform);
5941 addWindow(window);
5942
5943 // The following points in logical display space should be inside the window.
5944 static const std::array<vec2, 4> insidePoints{
5945 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5946 for (const auto pointInsideWindow : insidePoints) {
5947 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5948 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005949 mDispatcher->notifyMotion(
5950 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5951 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005952 window->consumeMotionDown();
5953
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005954 mDispatcher->notifyMotion(
5955 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5956 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005957 window->consumeMotionUp();
5958 }
5959
5960 // The following points in logical display space should be outside the window.
5961 static const std::array<vec2, 5> outsidePoints{
5962 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5963 for (const auto pointOutsideWindow : outsidePoints) {
5964 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5965 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005966 mDispatcher->notifyMotion(
5967 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5968 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005969
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005970 mDispatcher->notifyMotion(
5971 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5972 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005973 }
5974 window->assertNoEvents();
5975}
5976
Linnan Li5e5645e2024-03-05 14:43:05 +00005977// This test verifies the occlusion detection for all rotations of the display by tapping
5978// in different locations on the display, specifically points close to the four corners of a
5979// window.
5980TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) {
5981 constexpr static int32_t displayWidth = 400;
5982 constexpr static int32_t displayHeight = 800;
5983
5984 std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication =
5985 std::make_shared<FakeApplicationHandle>();
5986 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5987
5988 const auto rotation = GetParam();
5989
5990 // Set up the display with the specified rotation.
5991 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5992 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5993 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5994 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5995 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005996 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Linnan Li5e5645e2024-03-05 14:43:05 +00005997
5998 // Create a window that not trusted.
5999 const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
6000
6001 const Rect untrustedWindowFrameInDisplay =
6002 displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay);
6003
6004 sp<FakeWindowHandle> untrustedWindow =
6005 sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006006 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006007 untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
6008 untrustedWindow->setTrustedOverlay(false);
6009 untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
6010 untrustedWindow->setTouchable(false);
6011 untrustedWindow->setAlpha(1.0f);
6012 untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
6013 addWindow(untrustedWindow);
6014
6015 // Create a simple app window below the untrusted window.
6016 const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600);
6017 const Rect simpleAppWindowFrameInDisplay =
6018 displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay);
6019
6020 sp<FakeWindowHandle> simpleAppWindow =
6021 sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006022 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006023 simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
6024 simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
6025 addWindow(simpleAppWindow);
6026
6027 // The following points in logical display space should be inside the untrusted window, so
6028 // the simple window could not receive events that coordinate is these point.
6029 static const std::array<vec2, 4> untrustedPoints{
6030 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6031
6032 for (const auto untrustedPoint : untrustedPoints) {
6033 const vec2 p = displayTransform.inverse().transform(untrustedPoint);
6034 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006035 mDispatcher->notifyMotion(
6036 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6037 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6038 mDispatcher->notifyMotion(
6039 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6040 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Linnan Li5e5645e2024-03-05 14:43:05 +00006041 }
6042 untrustedWindow->assertNoEvents();
6043 simpleAppWindow->assertNoEvents();
6044 // The following points in logical display space should be outside the untrusted window, so
6045 // the simple window should receive events that coordinate is these point.
6046 static const std::array<vec2, 5> trustedPoints{
6047 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6048 for (const auto trustedPoint : trustedPoints) {
6049 const vec2 p = displayTransform.inverse().transform(trustedPoint);
6050 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006051 mDispatcher->notifyMotion(
6052 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6053 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6054 simpleAppWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006055 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006056 mDispatcher->notifyMotion(
6057 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6058 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6059 simpleAppWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006060 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6061 }
6062 untrustedWindow->assertNoEvents();
6063}
6064
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006065// Run the precision tests for all rotations.
6066INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
6067 InputDispatcherDisplayOrientationFixture,
6068 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6069 ui::ROTATION_270),
6070 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6071 return ftl::enum_string(testParamInfo.param);
6072 });
6073
Siarhei Vishniakou18050092021-09-01 13:32:49 -07006074using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
6075 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006076
6077class TransferTouchFixture : public InputDispatcherTest,
6078 public ::testing::WithParamInterface<TransferFunction> {};
6079
6080TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07006081 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006082
6083 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006084 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006085 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006086 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006087 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006088 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006089 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006090 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006091 sp<FakeWindowHandle> wallpaper =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006092 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
6093 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006094 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006095 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006096 mDispatcher->onWindowInfosChanged(
6097 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00006098 setFocusedWindow(firstWindow);
6099 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006100
6101 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006102 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006103 AINPUT_SOURCE_TOUCHSCREEN,
6104 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006105
Svet Ganov5d3bc372020-01-26 23:11:07 -08006106 // Only the first window should get the down event
6107 firstWindow->consumeMotionDown();
6108 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006109 wallpaper->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006110 // Dispatcher reports pointer down outside focus for the wallpaper
6111 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006112
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006113 // Transfer touch to the second window
6114 TransferFunction f = GetParam();
6115 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6116 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006117 // The first window gets cancel and the second gets down
6118 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006119 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6120 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6121 wallpaper->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006122 // There should not be any changes to the focused window when transferring touch
6123 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006124
6125 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006126 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006127 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00006128 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08006129 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006130 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6131 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006132 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006133}
6134
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006135/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00006136 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
6137 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
6138 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006139 * natural to the user.
6140 * In this test, we are sending a pointer to both spy window and first window. We then try to
6141 * transfer touch to the second window. The dispatcher should identify the first window as the
6142 * one that should lose the gesture, and therefore the action should be to move the gesture from
6143 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006144 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
6145 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006146 */
6147TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
6148 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6149
6150 // Create a couple of windows + a spy window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006151 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6152 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006153 spyWindow->setTrustedOverlay(true);
6154 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006155 sp<FakeWindowHandle> firstWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "First",
6156 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006157 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006158 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
6159 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006160
6161 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006162 mDispatcher->onWindowInfosChanged(
6163 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006164
6165 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006166 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006167 AINPUT_SOURCE_TOUCHSCREEN,
6168 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006169 // Only the first window and spy should get the down event
6170 spyWindow->consumeMotionDown();
6171 firstWindow->consumeMotionDown();
6172
6173 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00006174 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006175 TransferFunction f = GetParam();
6176 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6177 ASSERT_TRUE(success);
6178 // The first window gets cancel and the second gets down
6179 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006180 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6181 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006182
6183 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006184 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006185 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006186 // The first window gets no events and the second+spy get up
6187 firstWindow->assertNoEvents();
6188 spyWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006189 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6190 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006191}
6192
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006193TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006194 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006195
6196 PointF touchPoint = {10, 10};
6197
6198 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006199 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006200 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006201 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006202 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006203 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006204 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006205 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006206 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006207
6208 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006209 mDispatcher->onWindowInfosChanged(
6210 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006211
6212 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006213 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006214 AINPUT_SOURCE_TOUCHSCREEN,
6215 ui::LogicalDisplayId::DEFAULT, {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006216 // Only the first window should get the down event
6217 firstWindow->consumeMotionDown();
6218 secondWindow->assertNoEvents();
6219
6220 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006221 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006222 ui::LogicalDisplayId::DEFAULT,
6223 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006224 // Only the first window should get the pointer down event
6225 firstWindow->consumeMotionPointerDown(1);
6226 secondWindow->assertNoEvents();
6227
6228 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006229 TransferFunction f = GetParam();
6230 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6231 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006232 // The first window gets cancel and the second gets down and pointer down
6233 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006234 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6235 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6236 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006237 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006238
6239 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006240 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006241 ui::LogicalDisplayId::DEFAULT,
6242 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006243 // The first window gets nothing and the second gets pointer up
6244 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006245 secondWindow->consumeMotionPointerUp(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006246 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006247
6248 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006249 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006250 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006251 // The first window gets nothing and the second gets up
6252 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006253 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6254 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006255}
6256
Arthur Hungc539dbb2022-12-08 07:45:36 +00006257TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
6258 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6259
6260 // Create a couple of windows
6261 sp<FakeWindowHandle> firstWindow =
6262 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006263 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006264 firstWindow->setDupTouchToWallpaper(true);
6265 sp<FakeWindowHandle> secondWindow =
6266 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006267 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006268 secondWindow->setDupTouchToWallpaper(true);
6269
6270 sp<FakeWindowHandle> wallpaper1 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006271 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1",
6272 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006273 wallpaper1->setIsWallpaper(true);
6274
6275 sp<FakeWindowHandle> wallpaper2 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006276 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2",
6277 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006278 wallpaper2->setIsWallpaper(true);
6279 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006280 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
6281 *secondWindow->getInfo(), *wallpaper2->getInfo()},
6282 {},
6283 0,
6284 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00006285
6286 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006287 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006288 AINPUT_SOURCE_TOUCHSCREEN,
6289 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006290
6291 // Only the first window should get the down event
6292 firstWindow->consumeMotionDown();
6293 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006294 wallpaper1->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006295 wallpaper2->assertNoEvents();
6296
6297 // Transfer touch focus to the second window
6298 TransferFunction f = GetParam();
6299 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6300 ASSERT_TRUE(success);
6301
6302 // The first window gets cancel and the second gets down
6303 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006304 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6305 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6306 wallpaper1->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
6307 wallpaper2->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006308 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006309
6310 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006311 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006312 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006313 // The first window gets no events and the second gets up
6314 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006315 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6316 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006317 wallpaper1->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006318 wallpaper2->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006319 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006320}
6321
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006322// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00006323// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006324// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006325INSTANTIATE_TEST_SUITE_P(
6326 InputDispatcherTransferFunctionTests, TransferTouchFixture,
6327 ::testing::Values(
6328 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
6329 sp<IBinder> destChannelToken) {
6330 return dispatcher->transferTouchOnDisplay(destChannelToken,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006331 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006332 },
6333 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
6334 sp<IBinder> to) {
6335 return dispatcher->transferTouchGesture(from, to,
6336 /*isDragAndDrop=*/false);
6337 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006338
Prabir Pradhan367f3432024-02-13 23:05:58 +00006339TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006340 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006341
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006342 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006343 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006344 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006345 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006346
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006347 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006348 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006349 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006350 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006351
6352 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006353 mDispatcher->onWindowInfosChanged(
6354 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006355
6356 PointF pointInFirst = {300, 200};
6357 PointF pointInSecond = {300, 600};
6358
6359 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006360 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006361 AINPUT_SOURCE_TOUCHSCREEN,
6362 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006363 // Only the first window should get the down event
6364 firstWindow->consumeMotionDown();
6365 secondWindow->assertNoEvents();
6366
6367 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006368 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006369 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006370 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006371 // The first window gets a move and the second a down
6372 firstWindow->consumeMotionMove();
6373 secondWindow->consumeMotionDown();
6374
Prabir Pradhan367f3432024-02-13 23:05:58 +00006375 // Transfer touch to the second window
6376 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006377 // The first window gets cancel and the new gets pointer down (it already saw down)
6378 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006379 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006380 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006381
6382 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006383 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006384 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006385 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006386 // The first window gets nothing and the second gets pointer up
6387 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006388 secondWindow->consumeMotionPointerUp(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006389 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006390
6391 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006392 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006393 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006394 // The first window gets nothing and the second gets up
6395 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006396 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6397 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006398}
6399
Prabir Pradhan367f3432024-02-13 23:05:58 +00006400// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
6401// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
6402// receiving touch is not supported, so the touch should continue on those windows and the
6403// transferred-to window should get nothing.
6404TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006405 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6406
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006407 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006408 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006409 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006410 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006411
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006412 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006413 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006414 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006415 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006416
6417 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006418 mDispatcher->onWindowInfosChanged(
6419 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006420
6421 PointF pointInFirst = {300, 200};
6422 PointF pointInSecond = {300, 600};
6423
6424 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006425 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006426 AINPUT_SOURCE_TOUCHSCREEN,
6427 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006428 // Only the first window should get the down event
6429 firstWindow->consumeMotionDown();
6430 secondWindow->assertNoEvents();
6431
6432 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006433 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006434 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006435 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006436 // The first window gets a move and the second a down
6437 firstWindow->consumeMotionMove();
6438 secondWindow->consumeMotionDown();
6439
6440 // Transfer touch focus to the second window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006441 const bool transferred = mDispatcher->transferTouchOnDisplay(secondWindow->getToken(),
6442 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006443 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006444 ASSERT_FALSE(transferred);
6445 firstWindow->assertNoEvents();
6446 secondWindow->assertNoEvents();
6447
6448 // The rest of the dispatch should proceed as normal
6449 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006450 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006451 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006452 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006453 // The first window gets MOVE and the second gets pointer up
6454 firstWindow->consumeMotionMove();
6455 secondWindow->consumeMotionUp();
6456
6457 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006458 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006459 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006460 // The first window gets nothing and the second gets up
6461 firstWindow->consumeMotionUp();
6462 secondWindow->assertNoEvents();
6463}
6464
Arthur Hungabbb9d82021-09-01 14:52:30 +00006465// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00006466// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00006467// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006468TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006469 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6470 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006471 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6472 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006473 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006474 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006475 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6476 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006477 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006478
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006479 sp<FakeWindowHandle> mirrorWindowInPrimary =
6480 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006481 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006482
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006483 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006484 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006485
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006486 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006487 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006488
6489 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006490 mDispatcher->onWindowInfosChanged(
6491 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6492 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6493 *secondWindowInPrimary->getInfo()},
6494 {},
6495 0,
6496 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006497
6498 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006499 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6500 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006501 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6502
6503 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006504 firstWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006505
Prabir Pradhan367f3432024-02-13 23:05:58 +00006506 // Transfer touch
6507 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
6508 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006509 // The first window gets cancel.
6510 firstWindowInPrimary->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006511 secondWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006512 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006513
6514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006515 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006516 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006517 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6518 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006519 secondWindowInPrimary->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006520 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006521
6522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006523 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006524 {150, 50}))
6525 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6526 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006527 secondWindowInPrimary->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6528 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006529}
6530
Prabir Pradhan367f3432024-02-13 23:05:58 +00006531// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
6532// 'transferTouchOnDisplay' api.
6533TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006534 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6535 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006536 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6537 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006538 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006539 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006540 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6541 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006542 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006543
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006544 sp<FakeWindowHandle> mirrorWindowInPrimary =
6545 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006546 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006547
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006548 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006549 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006550
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006551 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006552 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006553
6554 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006555 mDispatcher->onWindowInfosChanged(
6556 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6557 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6558 *secondWindowInPrimary->getInfo()},
6559 {},
6560 0,
6561 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006562
6563 // Touch on second display.
6564 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006565 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6566 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006567 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6568
6569 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006570 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006571
6572 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00006573 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
6574 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006575
6576 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006577 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006578 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
6579 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006580
6581 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006582 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006583 SECOND_DISPLAY_ID, {150, 50}))
6584 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006585 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006586 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
6587 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006588
6589 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006590 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006591 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006592 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006593 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006594}
6595
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006596TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006597 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006598 sp<FakeWindowHandle> window =
6599 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6600 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006601
Vishnu Nair47074b82020-08-14 11:54:47 -07006602 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006603 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006604 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006605
6606 window->consumeFocusEvent(true);
6607
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006608 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006609
6610 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006611 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006612
6613 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006614 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006615 mFakePolicy->assertUserActivityPoked();
6616}
6617
6618TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
6619 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006620 sp<FakeWindowHandle> window =
6621 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6622 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006623
6624 window->setDisableUserActivity(true);
6625 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006626 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006627 setFocusedWindow(window);
6628
6629 window->consumeFocusEvent(true);
6630
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006631 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Josep del Riob3981622023-04-18 15:49:45 +00006632
6633 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006634 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006635
6636 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006637 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006638 mFakePolicy->assertUserActivityNotPoked();
6639}
6640
6641TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveSystemShortcut) {
6642 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006643 sp<FakeWindowHandle> window =
6644 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6645 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006646
6647 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006648 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006649 setFocusedWindow(window);
6650
6651 window->consumeFocusEvent(true);
6652
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006653 mDispatcher->notifyKey(
6654 generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Josep del Riob3981622023-04-18 15:49:45 +00006655 mDispatcher->waitForIdle();
6656
6657 // System key is not passed down
6658 window->assertNoEvents();
6659
6660 // Should have poked user activity
6661 mFakePolicy->assertUserActivityPoked();
6662}
6663
6664TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceiveAssistantKey) {
6665 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006666 sp<FakeWindowHandle> window =
6667 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6668 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006669
6670 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006671 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006672 setFocusedWindow(window);
6673
6674 window->consumeFocusEvent(true);
6675
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006676 mDispatcher->notifyKey(
6677 generateAssistantKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Josep del Riob3981622023-04-18 15:49:45 +00006678 mDispatcher->waitForIdle();
6679
6680 // System key is not passed down
6681 window->assertNoEvents();
6682
6683 // Should have poked user activity
6684 mFakePolicy->assertUserActivityPoked();
6685}
6686
6687TEST_F(InputDispatcherTest, FocusedWindow_SystemKeyIgnoresDisableUserActivity) {
6688 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006689 sp<FakeWindowHandle> window =
6690 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6691 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006692
6693 window->setDisableUserActivity(true);
6694 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006695 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006696 setFocusedWindow(window);
6697
6698 window->consumeFocusEvent(true);
6699
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006700 mDispatcher->notifyKey(
6701 generateSystemShortcutArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Josep del Riob3981622023-04-18 15:49:45 +00006702 mDispatcher->waitForIdle();
6703
6704 // System key is not passed down
6705 window->assertNoEvents();
6706
6707 // Should have poked user activity
6708 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006709}
6710
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006711TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
6712 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006713 sp<FakeWindowHandle> window =
6714 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6715 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006716
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006717 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006718
6719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006720 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006721 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006722 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6723
6724 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006725 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006726
6727 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006728 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006729 mFakePolicy->assertUserActivityPoked();
6730}
6731
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006732TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006733 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006734 sp<FakeWindowHandle> window =
6735 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6736 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006737
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006738 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006739
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006740 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006741 mDispatcher->waitForIdle();
6742
6743 window->assertNoEvents();
6744}
6745
6746// If a window is touchable, but does not have focus, it should receive motion events, but not keys
6747TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07006748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006749 sp<FakeWindowHandle> window =
6750 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6751 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006752
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006753 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006754
6755 // Send key
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006756 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006757 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00006758 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006759 AINPUT_SOURCE_TOUCHSCREEN,
6760 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006761
6762 // Window should receive only the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006763 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006764 window->assertNoEvents(); // Key event or focus event will not be received
6765}
6766
arthurhungea3f4fc2020-12-21 23:18:53 +08006767TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
6768 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6769
arthurhungea3f4fc2020-12-21 23:18:53 +08006770 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006771 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006772 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006773 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08006774
arthurhungea3f4fc2020-12-21 23:18:53 +08006775 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006776 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006777 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006778 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08006779
6780 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006781 mDispatcher->onWindowInfosChanged(
6782 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08006783
6784 PointF pointInFirst = {300, 200};
6785 PointF pointInSecond = {300, 600};
6786
6787 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006788 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006789 AINPUT_SOURCE_TOUCHSCREEN,
6790 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006791 // Only the first window should get the down event
6792 firstWindow->consumeMotionDown();
6793 secondWindow->assertNoEvents();
6794
6795 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006796 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006797 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006798 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006799 // The first window gets a move and the second a down
6800 firstWindow->consumeMotionMove();
6801 secondWindow->consumeMotionDown();
6802
6803 // Send pointer cancel to the second window
6804 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006805 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
6806 ui::LogicalDisplayId::DEFAULT, {pointInFirst, pointInSecond});
arthurhungea3f4fc2020-12-21 23:18:53 +08006807 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006808 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006809 // The first window gets move and the second gets cancel.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006810 firstWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6811 secondWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
arthurhungea3f4fc2020-12-21 23:18:53 +08006812
6813 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006814 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006815 ui::LogicalDisplayId::DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006816 // The first window gets up and the second gets nothing.
6817 firstWindow->consumeMotionUp();
6818 secondWindow->assertNoEvents();
6819}
6820
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006821TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6822 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6823
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006824 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6825 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006826 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006827 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6828 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6829 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6830
Harry Cutts33476232023-01-30 19:57:29 +00006831 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006832 window->assertNoEvents();
6833 mDispatcher->waitForIdle();
6834}
6835
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006836using InputDispatcherMonitorTest = InputDispatcherTest;
6837
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006838/**
6839 * Two entities that receive touch: A window, and a global monitor.
6840 * The touch goes to the window, and then the window disappears.
6841 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6842 * for the monitor, as well.
6843 * 1. foregroundWindow
6844 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6845 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006846TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006847 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006848 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
6849 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006850
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006851 FakeMonitorReceiver monitor =
6852 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006853
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006854 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006855 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006856 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6857 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006858 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6859
6860 // Both the foreground window and the global monitor should receive the touch down
6861 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006862 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006863
6864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006865 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006866 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006867 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6868
6869 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006870 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006871
6872 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006873 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006874 window->consumeMotionCancel();
6875 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6876
6877 // If more events come in, there will be no more foreground window to send them to. This will
6878 // cause a cancel for the monitor, as well.
6879 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006880 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006881 ui::LogicalDisplayId::DEFAULT, {120, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006882 << "Injection should fail because the window was removed";
6883 window->assertNoEvents();
6884 // Global monitor now gets the cancel
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006885 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006886}
6887
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006888TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006889 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006890 sp<FakeWindowHandle> window =
6891 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6892 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006893 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006894
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006895 FakeMonitorReceiver monitor =
6896 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006897
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006898 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006899 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6900 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006901 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006902 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
6903 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006904}
6905
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006906TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006907 FakeMonitorReceiver monitor =
6908 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006909
Chris Yea209fde2020-07-22 13:54:51 -07006910 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006911 sp<FakeWindowHandle> window =
6912 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6913 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006914 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006915
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006916 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006917 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6918 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006919 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006920 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
6921 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006922
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006923 // Pilfer pointers from the monitor.
6924 // This should not do anything and the window should continue to receive events.
6925 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006926
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006928 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006929 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006930 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006931
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006932 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
6933 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006934}
6935
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006936TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006937 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006938 sp<FakeWindowHandle> window =
6939 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6940 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006941 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006942 window->setWindowOffset(20, 40);
6943 window->setWindowTransform(0, 1, -1, 0);
6944
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006945 FakeMonitorReceiver monitor =
6946 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006947
6948 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006949 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6950 ui::LogicalDisplayId::DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006951 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006952 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006953 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6954 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006955 // Even though window has transform, gesture monitor must not.
6956 ASSERT_EQ(ui::Transform(), event->getTransform());
6957}
6958
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006959TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006960 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006961 FakeMonitorReceiver monitor =
6962 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006963
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006964 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006965 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6966 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006967 << "Injection should fail if there is a monitor, but no touchable window";
6968 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006969}
6970
Linnan Lid8150952024-01-26 18:07:17 +00006971/**
6972 * Two displays
6973 * The first monitor has a foreground window, a monitor
6974 * The second window has only one monitor.
6975 * We first inject a Down event into the first display, this injection should succeed and both
6976 * the foreground window and monitor should receive a down event, then inject a Down event into
6977 * the second display as well, this injection should fail, at this point, the first display
6978 * window and monitor should not receive a cancel or any other event.
6979 * Continue to inject Move and UP events to the first display, the events should be received
6980 * normally by the foreground window and monitor.
6981 */
6982TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
6983 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006984 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
6985 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006986
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006987 FakeMonitorReceiver monitor =
6988 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006989 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6990
6991 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006993 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6994 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00006995 << "The down event injected into the first display should succeed";
6996
6997 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006998 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006999
7000 ASSERT_EQ(InputEventInjectionResult::FAILED,
7001 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7002 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007003 << "The down event injected into the second display should fail since there's no "
7004 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007005
7006 // Continue to inject event to first display.
7007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7008 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007009 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007010 << "The move event injected into the first display should succeed";
7011
7012 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007013 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007014
7015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007016 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007017 {110, 220}))
7018 << "The up event injected into the first display should succeed";
7019
7020 window->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007021 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007022
7023 window->assertNoEvents();
7024 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007025 secondMonitor.assertNoEvents();
7026}
7027
7028/**
7029 * Two displays
7030 * There is a monitor and foreground window on each display.
7031 * First, we inject down events into each of the two displays, at this point, the foreground windows
7032 * and monitors on both displays should receive down events.
7033 * At this point, the foreground window of the second display goes away, the gone window should
7034 * receive the cancel event, and the other windows and monitors should not receive any events.
7035 * Inject a move event into the second display. At this point, the injection should fail because
7036 * the second display no longer has a foreground window. At this point, the monitor on the second
7037 * display should receive a cancel event, and any windows or monitors on the first display should
7038 * not receive any events, and any subsequent injection of events into the second display should
7039 * also fail.
7040 * Continue to inject events into the first display, and the events should all be injected
7041 * successfully and received normally.
7042 */
7043TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
7044 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007045 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7046 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007047 sp<FakeWindowHandle> secondWindow =
7048 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
7049 SECOND_DISPLAY_ID);
7050
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007051 FakeMonitorReceiver monitor =
7052 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007053 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7054
7055 // There is a foreground window on both displays.
7056 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7057 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007058 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7059 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007060 << "The down event injected into the first display should succeed";
7061
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007062 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7063 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007064
7065 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7066 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7067 {100, 200}))
7068 << "The down event injected into the second display should succeed";
7069
Linnan Lid8150952024-01-26 18:07:17 +00007070 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
7071 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
7072
7073 // Now second window is gone away.
7074 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7075
7076 // The gone window should receive a cancel, and the monitor on the second display should not
7077 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00007078 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
7079 secondMonitor.assertNoEvents();
7080
7081 ASSERT_EQ(InputEventInjectionResult::FAILED,
7082 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7083 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007084 << "The move event injected into the second display should fail because there's no "
7085 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007086 // Now the monitor on the second display should receive a cancel event.
7087 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00007088
7089 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7090 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007091 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007092 << "The move event injected into the first display should succeed";
7093
7094 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007095 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007096
7097 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007098 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7099 {110, 220}))
7100 << "The up event injected into the second display should fail because there's no "
7101 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007102
7103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007104 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007105 {110, 220}))
7106 << "The up event injected into the first display should succeed";
7107
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007108 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
7109 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007110
Linnan Lid8150952024-01-26 18:07:17 +00007111 window->assertNoEvents();
7112 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007113 secondWindow->assertNoEvents();
7114 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007115}
7116
7117/**
7118 * One display with transform
7119 * There is a foreground window and a monitor on the display
7120 * Inject down event and move event sequentially, the foreground window and monitor can receive down
7121 * event and move event, then let the foreground window go away, the foreground window receives
7122 * cancel event, inject move event again, the monitor receives cancel event, all the events received
7123 * by the monitor should be with the same transform as the display
7124 */
7125TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
7126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007127 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7128 ui::LogicalDisplayId::DEFAULT);
7129 FakeMonitorReceiver monitor =
7130 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007131
7132 ui::Transform transform;
7133 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7134
7135 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007136 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Linnan Lid8150952024-01-26 18:07:17 +00007137 displayInfo.transform = transform;
7138
7139 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
7140
7141 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007142 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7143 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007144 << "The down event injected should succeed";
7145
7146 window->consumeMotionDown();
7147 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
7148 EXPECT_EQ(transform, downMotionEvent->getTransform());
7149 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
7150
7151 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7152 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007153 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007154 << "The move event injected should succeed";
7155
7156 window->consumeMotionMove();
7157 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
7158 EXPECT_EQ(transform, moveMotionEvent->getTransform());
7159 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
7160
7161 // Let foreground window gone
7162 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
7163
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007164 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00007165 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00007166
7167 ASSERT_EQ(InputEventInjectionResult::FAILED,
7168 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007169 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007170 << "The move event injected should failed";
7171 // Now foreground should not receive any events, but monitor should receive a cancel event
7172 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00007173 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
7174 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007175 EXPECT_EQ(ui::LogicalDisplayId::DEFAULT, cancelMotionEvent->getDisplayId());
Linnan Lid8150952024-01-26 18:07:17 +00007176 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
7177
7178 // Other event inject to this display should fail.
7179 ASSERT_EQ(InputEventInjectionResult::FAILED,
7180 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007181 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007182 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00007183 window->assertNoEvents();
7184 monitor.assertNoEvents();
7185}
7186
chaviw81e2bb92019-12-18 15:03:51 -08007187TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007188 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007189 sp<FakeWindowHandle> window =
7190 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7191 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007192
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007193 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08007194
7195 NotifyMotionArgs motionArgs =
7196 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007197 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007198
Prabir Pradhan678438e2023-04-13 19:32:51 +00007199 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08007200 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007201 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007202
7203 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08007204 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08007205 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7206 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
7207 motionArgs.pointerCoords[0].getX() - 10);
7208
Prabir Pradhan678438e2023-04-13 19:32:51 +00007209 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007210 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08007211}
7212
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007213/**
7214 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
7215 * the device default right away. In the test scenario, we check both the default value,
7216 * and the action of enabling / disabling.
7217 */
7218TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07007219 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007220 sp<FakeWindowHandle> window =
7221 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7222 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08007223 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007224
7225 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007226 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007227 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007228
7229 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007230 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007231 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007232 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007233
7234 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007235 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007236 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007237 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007238
7239 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007240 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007241 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007242 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07007243 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007244 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007245 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007246 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007247
7248 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007249 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007250 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007251 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007252
7253 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007254 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007255 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007256 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07007257 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007258 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007259 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007260 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007261
7262 window->assertNoEvents();
7263}
7264
Gang Wange9087892020-01-07 12:17:14 -05007265TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007266 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007267 sp<FakeWindowHandle> window =
7268 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7269 ui::LogicalDisplayId::DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05007270
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007271 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007272 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05007273
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007274 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007275 setFocusedWindow(window);
7276
Harry Cutts33476232023-01-30 19:57:29 +00007277 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05007278
Prabir Pradhan678438e2023-04-13 19:32:51 +00007279 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
7280 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05007281
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007282 std::unique_ptr<KeyEvent> event = window->consumeKey();
7283 ASSERT_NE(event, nullptr);
7284 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05007285 ASSERT_NE(verified, nullptr);
7286 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
7287
7288 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
7289 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
7290 ASSERT_EQ(keyArgs.source, verified->source);
7291 ASSERT_EQ(keyArgs.displayId, verified->displayId);
7292
7293 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
7294
7295 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05007296 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007297 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05007298 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
7299 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
7300 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
7301 ASSERT_EQ(0, verifiedKey.repeatCount);
7302}
7303
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007304TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007305 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007306 sp<FakeWindowHandle> window =
7307 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7308 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007309
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007310 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007311
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007312 ui::Transform transform;
7313 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7314
7315 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007316 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007317 displayInfo.transform = transform;
7318
Patrick Williamsd828f302023-04-28 17:52:08 -05007319 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007320
Prabir Pradhan678438e2023-04-13 19:32:51 +00007321 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007322 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007323 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007324 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007325
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007326 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
7327 ASSERT_NE(nullptr, event);
7328 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007329 ASSERT_NE(verified, nullptr);
7330 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
7331
7332 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
7333 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
7334 EXPECT_EQ(motionArgs.source, verified->source);
7335 EXPECT_EQ(motionArgs.displayId, verified->displayId);
7336
7337 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
7338
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007339 const vec2 rawXY =
7340 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
7341 motionArgs.pointerCoords[0].getXYValue());
7342 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
7343 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007344 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007345 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007346 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007347 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
7348 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
7349}
7350
chaviw09c8d2d2020-08-24 15:48:26 -07007351/**
7352 * Ensure that separate calls to sign the same data are generating the same key.
7353 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
7354 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
7355 * tests.
7356 */
7357TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
7358 KeyEvent event = getTestKeyEvent();
7359 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7360
7361 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
7362 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
7363 ASSERT_EQ(hmac1, hmac2);
7364}
7365
7366/**
7367 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
7368 */
7369TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
7370 KeyEvent event = getTestKeyEvent();
7371 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7372 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
7373
7374 verifiedEvent.deviceId += 1;
7375 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7376
7377 verifiedEvent.source += 1;
7378 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7379
7380 verifiedEvent.eventTimeNanos += 1;
7381 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7382
Linnan Li13bf76a2024-05-05 19:18:02 +08007383 verifiedEvent.displayId = ui::LogicalDisplayId{verifiedEvent.displayId.val() + 1};
chaviw09c8d2d2020-08-24 15:48:26 -07007384 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7385
7386 verifiedEvent.action += 1;
7387 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7388
7389 verifiedEvent.downTimeNanos += 1;
7390 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7391
7392 verifiedEvent.flags += 1;
7393 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7394
7395 verifiedEvent.keyCode += 1;
7396 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7397
7398 verifiedEvent.scanCode += 1;
7399 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7400
7401 verifiedEvent.metaState += 1;
7402 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7403
7404 verifiedEvent.repeatCount += 1;
7405 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7406}
7407
Vishnu Nair958da932020-08-21 17:12:37 -07007408TEST_F(InputDispatcherTest, SetFocusedWindow) {
7409 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007410 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7411 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007412 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007413 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7414 ui::LogicalDisplayId::DEFAULT);
7415 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007416
7417 // Top window is also focusable but is not granted focus.
7418 windowTop->setFocusable(true);
7419 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007420 mDispatcher->onWindowInfosChanged(
7421 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007422 setFocusedWindow(windowSecond);
7423
7424 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007425 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007426 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007427
7428 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007429 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007430 windowTop->assertNoEvents();
7431}
7432
7433TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
7434 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007435 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7436 ui::LogicalDisplayId::DEFAULT);
7437 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007438
7439 window->setFocusable(true);
7440 // Release channel for window is no longer valid.
7441 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007442 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007443 setFocusedWindow(window);
7444
7445 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007446 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007447
7448 // window channel is invalid, so it should not receive any input event.
7449 window->assertNoEvents();
7450}
7451
7452TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
7453 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007454 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7455 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007456 window->setFocusable(false);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007457 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007458
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007459 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007460 setFocusedWindow(window);
7461
7462 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007463 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007464
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007465 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07007466 window->assertNoEvents();
7467}
7468
7469TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
7470 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007471 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7472 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007473 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007474 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7475 ui::LogicalDisplayId::DEFAULT);
7476 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007477
7478 windowTop->setFocusable(true);
7479 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007480 mDispatcher->onWindowInfosChanged(
7481 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007482 setFocusedWindow(windowTop);
7483 windowTop->consumeFocusEvent(true);
7484
Chavi Weingarten847e8512023-03-29 00:26:09 +00007485 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007486 mDispatcher->onWindowInfosChanged(
7487 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007488 windowSecond->consumeFocusEvent(true);
7489 windowTop->consumeFocusEvent(false);
7490
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007491 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007492 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007493
7494 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007495 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007496}
7497
Chavi Weingarten847e8512023-03-29 00:26:09 +00007498TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07007499 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007500 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7501 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007502 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007503 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7504 ui::LogicalDisplayId::DEFAULT);
7505 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007506
7507 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00007508 windowSecond->setFocusable(false);
7509 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007510 mDispatcher->onWindowInfosChanged(
7511 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00007512 setFocusedWindow(windowTop);
7513 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07007514
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007515 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00007516 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007517
7518 // Event should be dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007519 windowTop->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007520 windowSecond->assertNoEvents();
7521}
7522
7523TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
7524 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007525 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7526 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007527 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007528 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007529 ui::LogicalDisplayId::DEFAULT);
7530 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007531
7532 window->setFocusable(true);
7533 previousFocusedWindow->setFocusable(true);
7534 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007535 mDispatcher->onWindowInfosChanged(
7536 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007537 setFocusedWindow(previousFocusedWindow);
7538 previousFocusedWindow->consumeFocusEvent(true);
7539
7540 // Requesting focus on invisible window takes focus from currently focused window.
7541 setFocusedWindow(window);
7542 previousFocusedWindow->consumeFocusEvent(false);
7543
7544 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007546 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007547 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007548
7549 // Window does not get focus event or key down.
7550 window->assertNoEvents();
7551
7552 // Window becomes visible.
7553 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007554 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007555
7556 // Window receives focus event.
7557 window->consumeFocusEvent(true);
7558 // Focused window receives key down.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007559 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007560}
7561
Vishnu Nair599f1412021-06-21 10:39:58 -07007562TEST_F(InputDispatcherTest, DisplayRemoved) {
7563 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007564 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "window",
7565 ui::LogicalDisplayId::DEFAULT);
7566 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair599f1412021-06-21 10:39:58 -07007567
7568 // window is granted focus.
7569 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007570 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07007571 setFocusedWindow(window);
7572 window->consumeFocusEvent(true);
7573
7574 // When a display is removed window loses focus.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007575 mDispatcher->displayRemoved(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07007576 window->consumeFocusEvent(false);
7577}
7578
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007579/**
7580 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
7581 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
7582 * of the 'slipperyEnterWindow'.
7583 *
7584 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
7585 * a way so that the touched location is no longer covered by the top window.
7586 *
7587 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
7588 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
7589 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
7590 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
7591 * with ACTION_DOWN).
7592 * Thus, the touch has been transferred from the top window into the bottom window, because the top
7593 * window moved itself away from the touched location and had Flag::SLIPPERY.
7594 *
7595 * Even though the top window moved away from the touched location, it is still obscuring the bottom
7596 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
7597 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
7598 *
7599 * In this test, we ensure that the event received by the bottom window has
7600 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
7601 */
7602TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007603 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007604 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007605
7606 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007607 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007608
7609 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007610 sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7611 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007612 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007613 // Make sure this one overlaps the bottom window
7614 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
7615 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
7616 // one. Windows with the same owner are not considered to be occluding each other.
7617 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
7618
7619 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007620 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7621 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007622 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
7623
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007624 mDispatcher->onWindowInfosChanged(
7625 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007626
7627 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00007628 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007629 AINPUT_SOURCE_TOUCHSCREEN,
7630 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007631 slipperyExitWindow->consumeMotionDown();
7632 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007633 mDispatcher->onWindowInfosChanged(
7634 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007635
Prabir Pradhan678438e2023-04-13 19:32:51 +00007636 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007637 AINPUT_SOURCE_TOUCHSCREEN,
7638 ui::LogicalDisplayId::DEFAULT, {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007639
7640 slipperyExitWindow->consumeMotionCancel();
7641
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007642 slipperyEnterWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007643 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
7644}
7645
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007646/**
7647 * Two windows, one on the left and another on the right. The left window is slippery. The right
7648 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
7649 * touch moves from the left window into the right window, the gesture should continue to go to the
7650 * left window. Touch shouldn't slip because the right window can't receive touches. This test
7651 * reproduces a crash.
7652 */
7653TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
7654 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7655
7656 sp<FakeWindowHandle> leftSlipperyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007657 sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
7658 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007659 leftSlipperyWindow->setSlippery(true);
7660 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
7661
7662 sp<FakeWindowHandle> rightDropTouchesWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007663 sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
7664 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007665 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
7666 rightDropTouchesWindow->setDropInput(true);
7667
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007668 mDispatcher->onWindowInfosChanged(
7669 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007670
7671 // Start touch in the left window
7672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7673 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7674 .build());
7675 leftSlipperyWindow->consumeMotionDown();
7676
7677 // And move it into the right window
7678 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7679 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7680 .build());
7681
7682 // Since the right window isn't eligible to receive input, touch does not slip.
7683 // The left window continues to receive the gesture.
7684 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7685 rightDropTouchesWindow->assertNoEvents();
7686}
7687
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007688/**
7689 * A single window is on screen first. Touch is injected into that window. Next, a second window
7690 * appears. Since the first window is slippery, touch will move from the first window to the second.
7691 */
7692TEST_F(InputDispatcherTest, InjectedTouchSlips) {
7693 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7694 sp<FakeWindowHandle> originalWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007695 sp<FakeWindowHandle>::make(application, mDispatcher, "Original",
7696 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007697 originalWindow->setFrame(Rect(0, 0, 200, 200));
7698 originalWindow->setSlippery(true);
7699
7700 sp<FakeWindowHandle> appearingWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007701 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing",
7702 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007703 appearingWindow->setFrame(Rect(0, 0, 200, 200));
7704
7705 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
7706
7707 // Touch down on the original window
7708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7709 injectMotionEvent(*mDispatcher,
7710 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7711 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
7712 .build()));
7713 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7714
7715 // Now, a new window appears. This could be, for example, a notification shade that appears
7716 // after user starts to drag down on the launcher window.
7717 mDispatcher->onWindowInfosChanged(
7718 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
7719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7720 injectMotionEvent(*mDispatcher,
7721 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7722 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
7723 .build()));
7724 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7725 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7727 injectMotionEvent(*mDispatcher,
7728 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7729 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
7730 .build()));
7731 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7732
7733 originalWindow->assertNoEvents();
7734 appearingWindow->assertNoEvents();
7735}
7736
Linnan Li49b2b202024-04-12 12:46:40 +08007737/**
7738 * Three windows:
7739 * - left window, which has FLAG_SLIPPERY, so it supports slippery exit
7740 * - right window
7741 * - spy window
7742 * The three windows do not overlap.
7743 *
7744 * We have two devices reporting events:
7745 * - Device A reports ACTION_DOWN, which lands in the left window
7746 * - Device B reports ACTION_DOWN, which lands in the spy window.
7747 * - Now, device B reports ACTION_MOVE events which move to the right window.
7748 *
7749 * The right window should not receive any events because the spy window is not a foreground window,
7750 * and also it does not support slippery touches.
7751 */
7752TEST_F(InputDispatcherTest, MultiDeviceSpyWindowSlipTest) {
7753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7754 sp<FakeWindowHandle> leftWindow =
7755 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007756 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007757 leftWindow->setFrame(Rect(0, 0, 100, 100));
7758 leftWindow->setSlippery(true);
7759
7760 sp<FakeWindowHandle> rightWindow =
7761 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007762 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007763 rightWindow->setFrame(Rect(100, 0, 200, 100));
7764
7765 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007766 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
7767 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007768 spyWindow->setFrame(Rect(200, 0, 300, 100));
7769 spyWindow->setSpy(true);
7770 spyWindow->setTrustedOverlay(true);
7771
7772 mDispatcher->onWindowInfosChanged(
7773 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *spyWindow->getInfo()}, {}, 0, 0});
7774
7775 const DeviceId deviceA = 9;
7776 const DeviceId deviceB = 3;
7777
7778 // Tap on left window with device A
7779 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7780 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7781 .deviceId(deviceA)
7782 .build());
7783 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
7784
7785 // Tap on spy window with device B
7786 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7787 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
7788 .deviceId(deviceB)
7789 .build());
7790 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
7791
7792 // Move to right window with device B. Touches should not slip to the right window, because spy
7793 // window is not a foreground window, and it does not have FLAG_SLIPPERY
7794 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7795 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7796 .deviceId(deviceB)
7797 .build());
7798 leftWindow->assertNoEvents();
7799 rightWindow->assertNoEvents();
7800 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
7801}
7802
7803/**
7804 * Three windows arranged horizontally and without any overlap.
7805 * The left and right windows have FLAG_SLIPPERY. The middle window does not have any special flags.
7806 *
7807 * We have two devices reporting events:
7808 * - Device A reports ACTION_DOWN which lands in the left window
7809 * - Device B reports ACTION_DOWN which lands in the right window
7810 * - Device B reports ACTION_MOVE that shifts to the middle window.
7811 * This should cause touches for Device B to slip from the right window to the middle window.
7812 * The right window should receive ACTION_CANCEL for device B and the
7813 * middle window should receive down event for Device B.
7814 * If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
7815 */
7816TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
Siarhei Vishniakoudd56df12024-05-20 14:56:38 -07007817 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
Linnan Li49b2b202024-04-12 12:46:40 +08007818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7819 sp<FakeWindowHandle> leftWindow =
7820 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007821 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007822 leftWindow->setFrame(Rect(0, 0, 100, 100));
7823 leftWindow->setSlippery(true);
7824
7825 sp<FakeWindowHandle> middleWindow =
7826 sp<FakeWindowHandle>::make(application, mDispatcher, "middle window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007827 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007828 middleWindow->setFrame(Rect(100, 0, 200, 100));
7829
7830 sp<FakeWindowHandle> rightWindow =
7831 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007832 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007833 rightWindow->setFrame(Rect(200, 0, 300, 100));
7834 rightWindow->setSlippery(true);
7835
7836 mDispatcher->onWindowInfosChanged(
7837 {{*leftWindow->getInfo(), *middleWindow->getInfo(), *rightWindow->getInfo()},
7838 {},
7839 0,
7840 0});
7841
7842 const DeviceId deviceA = 9;
7843 const DeviceId deviceB = 3;
7844
7845 // Tap on left window with device A
7846 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7847 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7848 .deviceId(deviceA)
7849 .build());
7850 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
7851
7852 // Tap on right window with device B
7853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7854 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
7855 .deviceId(deviceB)
7856 .build());
7857 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
7858
7859 // Move to middle window with device B. Touches should slip to middle window, because right
7860 // window is a foreground window that's associated with device B and has FLAG_SLIPPERY.
7861 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7862 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7863 .deviceId(deviceB)
7864 .build());
7865 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
7866 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
7867
7868 // Move to middle window with device A. Touches should slip to middle window, because left
7869 // window is a foreground window that's associated with device A and has FLAG_SLIPPERY.
7870 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7871 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7872 .deviceId(deviceA)
7873 .build());
7874 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceA)));
7875 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
7876
7877 // Ensure that middle window can receive the remaining move events.
7878 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7879 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
7880 .deviceId(deviceB)
7881 .build());
7882 leftWindow->assertNoEvents();
7883 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
7884 rightWindow->assertNoEvents();
7885}
7886
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007887TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007888 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007889 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7890
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007891 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
7892 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007893 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007894 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007895
7896 sp<FakeWindowHandle> rightSpy =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007897 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy",
7898 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007899 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007900 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007901 rightSpy->setSpy(true);
7902 rightSpy->setTrustedOverlay(true);
7903
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007904 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
7905 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007906 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007907 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007908
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007909 mDispatcher->onWindowInfosChanged(
7910 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007911
7912 // Touch in the left window
7913 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7914 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7915 .build());
7916 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
7917 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007918 ASSERT_NO_FATAL_FAILURE(
7919 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007920
7921 // Touch another finger over the right windows
7922 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7923 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7924 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7925 .build());
7926 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
7927 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
7928 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
7929 mDispatcher->waitForIdle();
7930 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007931 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
7932 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007933
7934 // Release finger over left window. The UP actions are not treated as device interaction.
7935 // The windows that did not receive the UP pointer will receive MOVE events, but since this
7936 // is part of the UP action, we do not treat this as device interaction.
7937 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
7938 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7939 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7940 .build());
7941 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
7942 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7943 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7944 mDispatcher->waitForIdle();
7945 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7946
7947 // Move remaining finger
7948 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7949 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7950 .build());
7951 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7952 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7953 mDispatcher->waitForIdle();
7954 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007955 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007956
7957 // Release all fingers
7958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7959 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7960 .build());
7961 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
7962 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
7963 mDispatcher->waitForIdle();
7964 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7965}
7966
7967TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
7968 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7969
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007970 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
7971 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007972 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007973 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007974
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007975 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007976 setFocusedWindow(window);
7977 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
7978
7979 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007980 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007981 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007982 ASSERT_NO_FATAL_FAILURE(
7983 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007984
7985 // The UP actions are not treated as device interaction.
7986 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007987 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007988 mDispatcher->waitForIdle();
7989 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7990}
7991
Prabir Pradhan5893d362023-11-17 04:30:40 +00007992TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
7993 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7994
7995 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007996 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007997 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007998 sp<FakeWindowHandle> right =
7999 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
8000 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008001 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008002 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8003 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008004 spy->setFrame(Rect(0, 0, 200, 100));
8005 spy->setTrustedOverlay(true);
8006 spy->setSpy(true);
8007
8008 mDispatcher->onWindowInfosChanged(
8009 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
8010
8011 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008012 NotifyMotionArgs notifyArgs =
8013 generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8014 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008015 mDispatcher->notifyMotion(notifyArgs);
8016
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008017 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008018 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
8019 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008020 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008021 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8022 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008023 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008024 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8025
8026 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008027 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8028 ui::LogicalDisplayId::DEFAULT, {PointF{150, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008029 mDispatcher->notifyMotion(notifyArgs);
8030
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008031 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008032 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
8033 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008034 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008035 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8036 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008037 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008038 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8039
8040 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
8041}
8042
Linnan Liccf6ce32024-04-11 20:32:13 +08008043/**
8044 * When a device reports a DOWN event, which lands in a window that supports splits, and then the
8045 * device then reports a POINTER_DOWN, which lands in the location of a non-existing window, then
8046 * the previous window should receive this event and not be dropped.
8047 */
8048TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
8049 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008050 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8051 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008052 window->setFrame(Rect(0, 0, 100, 100));
8053 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8054
8055 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8056 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8057 .build());
8058
8059 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
8060
8061 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8062 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8063 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
8064 .build());
8065
8066 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_1_DOWN)));
8067}
8068
8069/**
8070 * When deviceA reports a DOWN event, which lands in a window that supports splits, and then deviceB
8071 * also reports a DOWN event, which lands in the location of a non-existing window, then the
8072 * previous window should receive deviceB's event and it should be dropped.
8073 */
8074TEST_F(InputDispatcherMultiDeviceTest, SecondDeviceDownEventDroppedWithoutWindowTarget) {
8075 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008076 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8077 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008078 window->setFrame(Rect(0, 0, 100, 100));
8079 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8080
8081 const DeviceId deviceA = 9;
8082 const DeviceId deviceB = 3;
8083
8084 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8085 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8086 .deviceId(deviceA)
8087 .build());
8088 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8089
8090 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8091 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
8092 .deviceId(deviceB)
8093 .build());
8094 window->assertNoEvents();
8095}
8096
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008097class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
8098protected:
8099 std::shared_ptr<FakeApplicationHandle> mApp;
8100 sp<FakeWindowHandle> mWindow;
8101
8102 virtual void SetUp() override {
8103 InputDispatcherTest::SetUp();
8104
8105 mApp = std::make_shared<FakeApplicationHandle>();
8106
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008107 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window",
8108 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008109 mWindow->setFrame(Rect(0, 0, 100, 100));
8110
8111 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8112 setFocusedWindow(mWindow);
8113 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
8114 }
8115
8116 void setFallback(int32_t keycode) {
8117 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
8118 return KeyEventBuilder(event).keyCode(keycode).build();
8119 });
8120 }
8121
8122 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008123 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
8124 ASSERT_NE(nullptr, event);
8125 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008126 }
8127};
8128
8129TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
8130 mDispatcher->notifyKey(
8131 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8132 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8133 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8134}
8135
8136TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
8137 mDispatcher->notifyKey(
8138 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8139 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8140 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8141}
8142
8143TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
8144 mDispatcher->notifyKey(
8145 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8146
8147 // Do not handle this key event.
8148 consumeKey(/*handled=*/false,
8149 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8150 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8151
8152 // Since the policy did not request any fallback to be generated, ensure there are no events.
8153 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8154}
8155
8156TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
8157 setFallback(AKEYCODE_B);
8158 mDispatcher->notifyKey(
8159 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8160
8161 // Do not handle this key event.
8162 consumeKey(/*handled=*/false,
8163 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8164
8165 // Since the key was not handled, ensure the fallback event was dispatched instead.
8166 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8167 consumeKey(/*handled=*/true,
8168 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8169 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8170
8171 // Release the original key, and ensure the fallback key is also released.
8172 mDispatcher->notifyKey(
8173 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8174 consumeKey(/*handled=*/false,
8175 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8176 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8177 consumeKey(/*handled=*/true,
8178 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8179 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8180
8181 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8182 mWindow->assertNoEvents();
8183}
8184
8185TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
8186 setFallback(AKEYCODE_B);
8187 mDispatcher->notifyKey(
8188 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8189
8190 // Do not handle this key event, but handle the fallback.
8191 consumeKey(/*handled=*/false,
8192 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8193 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8194 consumeKey(/*handled=*/true,
8195 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8196 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8197
8198 // Release the original key, and ensure the fallback key is also released.
8199 mDispatcher->notifyKey(
8200 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8201 // But this time, the app handles the original key.
8202 consumeKey(/*handled=*/true,
8203 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8204 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8205 // Ensure the fallback key is canceled.
8206 consumeKey(/*handled=*/true,
8207 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8208 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8209
8210 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8211 mWindow->assertNoEvents();
8212}
8213
8214TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
8215 setFallback(AKEYCODE_B);
8216 mDispatcher->notifyKey(
8217 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8218
8219 // Do not handle this key event.
8220 consumeKey(/*handled=*/false,
8221 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8222 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8223 // App does not handle the fallback either, so ensure another fallback is not generated.
8224 setFallback(AKEYCODE_C);
8225 consumeKey(/*handled=*/false,
8226 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8227 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8228
8229 // Release the original key, and ensure the fallback key is also released.
8230 setFallback(AKEYCODE_B);
8231 mDispatcher->notifyKey(
8232 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8233 consumeKey(/*handled=*/false,
8234 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8235 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8236 consumeKey(/*handled=*/false,
8237 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8238 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8239
8240 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8241 mWindow->assertNoEvents();
8242}
8243
8244TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
8245 setFallback(AKEYCODE_B);
8246 mDispatcher->notifyKey(
8247 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8248
8249 // Do not handle this key event, so fallback is generated.
8250 consumeKey(/*handled=*/false,
8251 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8252 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8253 consumeKey(/*handled=*/true,
8254 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8255 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8256
8257 // Release the original key, but assume the policy is misbehaving and it
8258 // generates an inconsistent fallback to the one from the DOWN event.
8259 setFallback(AKEYCODE_C);
8260 mDispatcher->notifyKey(
8261 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8262 consumeKey(/*handled=*/false,
8263 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8264 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8265 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
8266 consumeKey(/*handled=*/true,
8267 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8268 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8269
8270 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8271 mWindow->assertNoEvents();
8272}
8273
8274TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
8275 setFallback(AKEYCODE_B);
8276 mDispatcher->notifyKey(
8277 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8278
8279 // Do not handle this key event, so fallback is generated.
8280 consumeKey(/*handled=*/false,
8281 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8282 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8283 consumeKey(/*handled=*/true,
8284 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8285 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8286
8287 // The original key is canceled.
8288 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
8289 .keyCode(AKEYCODE_A)
8290 .addFlag(AKEY_EVENT_FLAG_CANCELED)
8291 .build());
8292 consumeKey(/*handled=*/false,
8293 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8294 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8295 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8296 // Ensure the fallback key is also canceled due to the original key being canceled.
8297 consumeKey(/*handled=*/true,
8298 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8299 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8300
8301 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8302 mWindow->assertNoEvents();
8303}
8304
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008305TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00008306 setFallback(AKEYCODE_B);
8307 mDispatcher->notifyKey(
8308 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8309
8310 // Do not handle this key event.
8311 consumeKey(/*handled=*/false,
8312 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8313 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8314 consumeKey(/*handled=*/true,
8315 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8316 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8317
8318 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8319 // When the unhandled key is reported to the policy next, remove the input channel.
8320 mDispatcher->removeInputChannel(mWindow->getToken());
8321 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8322 });
8323 // Release the original key, and let the app now handle the previously unhandled key.
8324 // This should result in the previously generated fallback key to be cancelled.
8325 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
8326 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
8327 // without holding the lock, because it need to synchronously fetch the fallback key. While in
8328 // the policy call, we will now remove the input channel. Once the policy call returns, the
8329 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
8330 // not cause any crashes.
8331 mDispatcher->notifyKey(
8332 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8333 consumeKey(/*handled=*/true,
8334 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8335 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8336}
8337
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008338TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
8339 setFallback(AKEYCODE_B);
8340 mDispatcher->notifyKey(
8341 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8342
8343 // Do not handle this key event.
8344 consumeKey(/*handled=*/false,
8345 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8346 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8347 consumeKey(/*handled=*/true,
8348 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8349 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8350
8351 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8352 // When the unhandled key is reported to the policy next, remove the window.
8353 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8354 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8355 });
8356 // Release the original key, which the app will not handle. When this unhandled key is reported
8357 // to the policy, the window will be removed.
8358 mDispatcher->notifyKey(
8359 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8360 consumeKey(/*handled=*/false,
8361 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8362 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8363
8364 // Since the window was removed, it loses focus, and the channel state will be reset.
8365 consumeKey(/*handled=*/true,
8366 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8367 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8368 mWindow->consumeFocusEvent(false);
8369 mWindow->assertNoEvents();
8370}
8371
8372TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
8373 setFallback(AKEYCODE_B);
8374 mDispatcher->notifyKey(
8375 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8376
8377 // Do not handle this key event.
8378 consumeKey(/*handled=*/false,
8379 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8380 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8381 const auto [seq, event] = mWindow->receiveEvent();
8382 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
8383 ASSERT_EQ(event->getType(), InputEventType::KEY);
8384 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
8385 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8386 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8387
8388 // Remove the window now, which should generate a cancellations and make the window lose focus.
8389 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8390 consumeKey(/*handled=*/true,
8391 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8392 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8393 consumeKey(/*handled=*/true,
8394 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8395 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8396 mWindow->consumeFocusEvent(false);
8397
8398 // Finish the event by reporting it as handled.
8399 mWindow->finishEvent(*seq);
8400 mWindow->assertNoEvents();
8401}
8402
Garfield Tan1c7bc862020-01-28 13:24:04 -08008403class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
8404protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08008405 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
8406 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008407
Chris Yea209fde2020-07-22 13:54:51 -07008408 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008409 sp<FakeWindowHandle> mWindow;
8410
8411 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00008412 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008413
Prabir Pradhandae52792023-12-15 07:36:40 +00008414 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008415 setUpWindow();
8416 }
8417
8418 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07008419 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008420 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window",
8421 ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008422
Vishnu Nair47074b82020-08-14 11:54:47 -07008423 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008424 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008425 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008426 mWindow->consumeFocusEvent(true);
8427 }
8428
Chris Ye2ad95392020-09-01 13:44:44 -07008429 void sendAndConsumeKeyDown(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008430 NotifyKeyArgs keyArgs =
8431 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008432 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008433 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008434 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008435
8436 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008437 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008438 }
8439
8440 void expectKeyRepeatOnce(int32_t repeatCount) {
8441 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008442 mWindow->consumeKeyEvent(
8443 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008444 }
8445
Chris Ye2ad95392020-09-01 13:44:44 -07008446 void sendAndConsumeKeyUp(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008447 NotifyKeyArgs keyArgs =
8448 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008449 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008450 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008451 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008452
8453 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008454 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008455 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008456 }
Hu Guofe3c8f12023-09-22 17:20:15 +08008457
8458 void injectKeyRepeat(int32_t repeatCount) {
8459 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008460 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount,
8461 ui::LogicalDisplayId::DEFAULT))
Hu Guofe3c8f12023-09-22 17:20:15 +08008462 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8463 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08008464};
8465
8466TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00008467 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008468 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8469 expectKeyRepeatOnce(repeatCount);
8470 }
8471}
8472
8473TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00008474 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008475 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8476 expectKeyRepeatOnce(repeatCount);
8477 }
Harry Cutts33476232023-01-30 19:57:29 +00008478 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008479 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08008480 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8481 expectKeyRepeatOnce(repeatCount);
8482 }
8483}
8484
8485TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008486 sendAndConsumeKeyDown(/*deviceId=*/1);
8487 expectKeyRepeatOnce(/*repeatCount=*/1);
8488 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008489 mWindow->assertNoEvents();
8490}
8491
8492TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008493 sendAndConsumeKeyDown(/*deviceId=*/1);
8494 expectKeyRepeatOnce(/*repeatCount=*/1);
8495 sendAndConsumeKeyDown(/*deviceId=*/2);
8496 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008497 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00008498 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008499 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00008500 expectKeyRepeatOnce(/*repeatCount=*/2);
8501 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07008502 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00008503 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008504 mWindow->assertNoEvents();
8505}
8506
8507TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008508 sendAndConsumeKeyDown(/*deviceId=*/1);
8509 expectKeyRepeatOnce(/*repeatCount=*/1);
8510 sendAndConsumeKeyDown(/*deviceId=*/2);
8511 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008512 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00008513 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008514 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08008515 mWindow->assertNoEvents();
8516}
8517
liushenxiang42232912021-05-21 20:24:09 +08008518TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
8519 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00008520 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008521 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008522 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
liushenxiang42232912021-05-21 20:24:09 +08008523 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
8524 mWindow->assertNoEvents();
8525}
8526
Garfield Tan1c7bc862020-01-28 13:24:04 -08008527TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008528 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008529 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008530 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008531 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8532 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008533 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008534 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008535 }
8536}
8537
8538TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008539 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008540 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008541
8542 std::unordered_set<int32_t> idSet;
8543 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008544 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8545 ASSERT_NE(nullptr, repeatEvent);
8546 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008547 EXPECT_EQ(idSet.end(), idSet.find(id));
8548 idSet.insert(id);
8549 }
8550}
8551
Hu Guofe3c8f12023-09-22 17:20:15 +08008552TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
8553 injectKeyRepeat(0);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008554 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Hu Guofe3c8f12023-09-22 17:20:15 +08008555 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
8556 expectKeyRepeatOnce(repeatCount);
8557 }
8558 injectKeyRepeat(1);
8559 // Expect repeatCount to be 3 instead of 1
8560 expectKeyRepeatOnce(3);
8561}
8562
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008563/* Test InputDispatcher for MultiDisplay */
8564class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
8565public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008566 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008567 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08008568
Chris Yea209fde2020-07-22 13:54:51 -07008569 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008570 windowInPrimary = sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1",
8571 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008572
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008573 // Set focus window for primary display, but focused display would be second one.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008574 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07008575 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008576 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
8577
Vishnu Nair958da932020-08-21 17:12:37 -07008578 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008579 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08008580
Chris Yea209fde2020-07-22 13:54:51 -07008581 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008582 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008583 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008584 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008585 // Set focus display to second one.
8586 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
8587 // Set focus window for second display.
8588 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07008589 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008590 mDispatcher->onWindowInfosChanged(
8591 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008592 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008593 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008594 }
8595
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008596 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008597 InputDispatcherTest::TearDown();
8598
Chris Yea209fde2020-07-22 13:54:51 -07008599 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008600 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07008601 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008602 windowInSecondary.clear();
8603 }
8604
8605protected:
Chris Yea209fde2020-07-22 13:54:51 -07008606 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008607 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07008608 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008609 sp<FakeWindowHandle> windowInSecondary;
8610};
8611
8612TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
8613 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008615 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8616 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008617 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008618 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08008619 windowInSecondary->assertNoEvents();
8620
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008621 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008623 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008624 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08008625 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08008626 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08008627}
8628
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008629TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08008630 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008632 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008633 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008634 windowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08008635 windowInSecondary->assertNoEvents();
8636
8637 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008638 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008639 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08008640 windowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008641 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hungb92218b2018-08-14 12:00:21 +08008642
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008643 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008644 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08008645
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008646 // Old focus should receive a cancel event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008647 windowInSecondary->consumeKeyUp(ui::LogicalDisplayId::INVALID, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08008648
8649 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008650 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08008651 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008652 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08008653 windowInSecondary->assertNoEvents();
8654}
8655
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008656// Test per-display input monitors for motion event.
8657TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08008658 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008659 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08008660 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008661 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008662
8663 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008665 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8666 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008667 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008668 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
8669 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008670 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008671 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008672
8673 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008675 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008676 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008677 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008678 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08008679 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08008680 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008681
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08008682 // Lift up the touch from the second display
8683 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008684 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08008685 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8686 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
8687 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
8688
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008689 // Test inject a non-pointer motion event.
8690 // If specific a display, it will dispatch to the focused window of particular display,
8691 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008693 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL,
8694 ui::LogicalDisplayId::INVALID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008696 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008697 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008698 windowInSecondary->consumeMotionDown(ui::LogicalDisplayId::INVALID);
8699 monitorInSecondary.consumeMotionDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008700}
8701
8702// Test per-display input monitors for key event.
8703TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008704 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08008705 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008706 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08008707 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008708 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008709
8710 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008711 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008712 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008713 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008714 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008715 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
8716 monitorInSecondary.consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008717}
8718
Vishnu Nair958da932020-08-21 17:12:37 -07008719TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
8720 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008721 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2",
8722 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008723 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008724 mDispatcher->onWindowInfosChanged(
8725 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
8726 *windowInSecondary->getInfo()},
8727 {},
8728 0,
8729 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008730 setFocusedWindow(secondWindowInPrimary);
8731 windowInPrimary->consumeFocusEvent(false);
8732 secondWindowInPrimary->consumeFocusEvent(true);
8733
8734 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008735 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008736 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008737 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008738 windowInPrimary->assertNoEvents();
8739 windowInSecondary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008740 secondWindowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008741}
8742
Arthur Hungdfd528e2021-12-08 13:23:04 +00008743TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
8744 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008745 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008746 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008747 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008748
8749 // Test touch down on primary display.
8750 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008751 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8752 ui::LogicalDisplayId::DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008753 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008754 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
8755 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008756
8757 // Test touch down on second display.
8758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008759 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008760 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8761 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
8762 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
8763
8764 // Trigger cancel touch.
8765 mDispatcher->cancelCurrentTouch();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008766 windowInPrimary->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
8767 monitorInPrimary.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008768 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
8769 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
8770
8771 // Test inject a move motion event, no window/monitor should receive the event.
8772 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008773 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008774 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008775 << "Inject motion event should return InputEventInjectionResult::FAILED";
8776 windowInPrimary->assertNoEvents();
8777 monitorInPrimary.assertNoEvents();
8778
8779 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008780 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00008781 SECOND_DISPLAY_ID, {110, 200}))
8782 << "Inject motion event should return InputEventInjectionResult::FAILED";
8783 windowInSecondary->assertNoEvents();
8784 monitorInSecondary.assertNoEvents();
8785}
8786
Hu Guocb134f12023-12-23 13:42:44 +00008787/**
8788 * Send a key to the primary display and to the secondary display.
8789 * Then cause the key on the primary display to be canceled by sending in a stale key.
8790 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
8791 * does not get canceled.
8792 */
8793TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
8794 // Send a key down on primary display
8795 mDispatcher->notifyKey(
8796 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008797 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008798 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8799 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008800 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
8801 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00008802 windowInSecondary->assertNoEvents();
8803
8804 // Send a key down on second display
8805 mDispatcher->notifyKey(
8806 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8807 .displayId(SECOND_DISPLAY_ID)
8808 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8809 .build());
8810 windowInSecondary->consumeKeyEvent(
8811 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
8812 windowInPrimary->assertNoEvents();
8813
8814 // Send a valid key up event on primary display that will be dropped because it is stale
8815 NotifyKeyArgs staleKeyUp =
8816 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008817 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008818 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8819 .build();
8820 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
8821 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
8822 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
8823 mDispatcher->notifyKey(staleKeyUp);
8824
8825 // Only the key gesture corresponding to the dropped event should receive the cancel event.
8826 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
8827 // receive any events.
8828 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008829 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
Hu Guocb134f12023-12-23 13:42:44 +00008830 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8831 windowInSecondary->assertNoEvents();
8832}
8833
8834/**
8835 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
8836 */
8837TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
8838 // Send touch down on primary display.
8839 mDispatcher->notifyMotion(
8840 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8841 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008842 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008843 .build());
8844 windowInPrimary->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008845 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00008846 windowInSecondary->assertNoEvents();
8847
8848 // Send touch down on second display.
8849 mDispatcher->notifyMotion(
8850 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8851 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8852 .displayId(SECOND_DISPLAY_ID)
8853 .build());
8854 windowInPrimary->assertNoEvents();
8855 windowInSecondary->consumeMotionEvent(
8856 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
8857
8858 // inject a valid MotionEvent on primary display that will be stale when it arrives.
8859 NotifyMotionArgs staleMotionUp =
8860 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008861 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008862 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8863 .build();
8864 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
8865 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
8866 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
8867 mDispatcher->notifyMotion(staleMotionUp);
8868
8869 // For stale motion events, we let the gesture to complete. This behaviour is different from key
8870 // events, where we would cancel the current keys instead.
8871 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
8872 windowInSecondary->assertNoEvents();
8873}
8874
Jackal Guof9696682018-10-05 12:23:23 +08008875class InputFilterTest : public InputDispatcherTest {
8876protected:
Linnan Li13bf76a2024-05-05 19:18:02 +08008877 void testNotifyMotion(ui::LogicalDisplayId displayId, bool expectToBeFiltered,
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008878 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08008879 NotifyMotionArgs motionArgs;
8880
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008881 motionArgs =
8882 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008883 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008884 motionArgs =
8885 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008886 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008887 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08008888 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07008889 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008890 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08008891 } else {
8892 mFakePolicy->assertFilterInputEventWasNotCalled();
8893 }
8894 }
8895
8896 void testNotifyKey(bool expectToBeFiltered) {
8897 NotifyKeyArgs keyArgs;
8898
8899 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008900 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08008901 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008902 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008903 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08008904
8905 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08008906 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08008907 } else {
8908 mFakePolicy->assertFilterInputEventWasNotCalled();
8909 }
8910 }
8911};
8912
8913// Test InputFilter for MotionEvent
8914TEST_F(InputFilterTest, MotionEvent_InputFilter) {
8915 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008916 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00008917 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008918
8919 // Enable InputFilter
8920 mDispatcher->setInputFilterEnabled(true);
8921 // Test touch on both primary and second display, and check if both events are filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008922 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true);
Harry Cutts101ee9b2023-07-06 18:04:14 +00008923 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08008924
8925 // Disable InputFilter
8926 mDispatcher->setInputFilterEnabled(false);
8927 // Test touch on both primary and second display, and check if both events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008928 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00008929 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008930}
8931
8932// Test InputFilter for KeyEvent
8933TEST_F(InputFilterTest, KeyEvent_InputFilter) {
8934 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008935 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008936
8937 // Enable InputFilter
8938 mDispatcher->setInputFilterEnabled(true);
8939 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008940 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08008941
8942 // Disable InputFilter
8943 mDispatcher->setInputFilterEnabled(false);
8944 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008945 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008946}
8947
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008948// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
8949// logical display coordinate space.
8950TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
8951 ui::Transform firstDisplayTransform;
8952 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
8953 ui::Transform secondDisplayTransform;
8954 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
8955
8956 std::vector<gui::DisplayInfo> displayInfos(2);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008957 displayInfos[0].displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008958 displayInfos[0].transform = firstDisplayTransform;
8959 displayInfos[1].displayId = SECOND_DISPLAY_ID;
8960 displayInfos[1].transform = secondDisplayTransform;
8961
Patrick Williamsd828f302023-04-28 17:52:08 -05008962 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008963
8964 // Enable InputFilter
8965 mDispatcher->setInputFilterEnabled(true);
8966
8967 // Ensure the correct transforms are used for the displays.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008968 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true,
8969 firstDisplayTransform);
Harry Cutts101ee9b2023-07-06 18:04:14 +00008970 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008971}
8972
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008973class InputFilterInjectionPolicyTest : public InputDispatcherTest {
8974protected:
8975 virtual void SetUp() override {
8976 InputDispatcherTest::SetUp();
8977
8978 /**
8979 * We don't need to enable input filter to test the injected event policy, but we enabled it
8980 * here to make the tests more realistic, since this policy only matters when inputfilter is
8981 * on.
8982 */
8983 mDispatcher->setInputFilterEnabled(true);
8984
8985 std::shared_ptr<InputApplicationHandle> application =
8986 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008987 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008988 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008989
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008990 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008991 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008992 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008993 setFocusedWindow(mWindow);
8994 mWindow->consumeFocusEvent(true);
8995 }
8996
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008997 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8998 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008999 KeyEvent event;
9000
9001 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9002 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009003 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
9004 AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009005 const int32_t additionalPolicyFlags =
9006 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
9007 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009008 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009009 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009010 policyFlags | additionalPolicyFlags));
9011
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009012 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009013 }
9014
9015 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9016 int32_t flags) {
9017 MotionEvent event;
9018 PointerProperties pointerProperties[1];
9019 PointerCoords pointerCoords[1];
9020 pointerProperties[0].clear();
9021 pointerProperties[0].id = 0;
9022 pointerCoords[0].clear();
9023 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
9024 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
9025
9026 ui::Transform identityTransform;
9027 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9028 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
9029 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
9030 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
9031 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07009032 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07009033 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00009034 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009035
9036 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
9037 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009038 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009039 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009040 policyFlags | additionalPolicyFlags));
9041
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009042 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009043 }
9044
9045private:
9046 sp<FakeWindowHandle> mWindow;
9047};
9048
9049TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009050 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
9051 // filter. Without it, the event will no different from a regularly injected event, and the
9052 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00009053 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
9054 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009055}
9056
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009057TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009058 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009059 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009060 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
9061}
9062
9063TEST_F(InputFilterInjectionPolicyTest,
9064 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
9065 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009066 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009067 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009068}
9069
9070TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00009071 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
9072 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009073}
9074
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009075class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
9076protected:
9077 virtual void SetUp() override {
9078 InputDispatcherTest::SetUp();
9079
9080 std::shared_ptr<FakeApplicationHandle> application =
9081 std::make_shared<FakeApplicationHandle>();
9082 application->setDispatchingTimeout(100ms);
9083 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009084 ui::LogicalDisplayId::DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00009085 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009086 mWindow->setDispatchingTimeout(100ms);
9087 mWindow->setFocusable(true);
9088
9089 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009090 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009091
9092 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
9093 setFocusedWindow(mWindow);
9094 mWindow->consumeFocusEvent(true);
9095 }
9096
Linnan Li13bf76a2024-05-05 19:18:02 +08009097 void notifyAndConsumeMotion(int32_t action, uint32_t source, ui::LogicalDisplayId displayId,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009098 nsecs_t eventTime) {
9099 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
9100 .displayId(displayId)
9101 .eventTime(eventTime)
9102 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9103 .build());
9104 mWindow->consumeMotionEvent(WithMotionAction(action));
9105 }
9106
9107private:
9108 sp<FakeWindowHandle> mWindow;
9109};
9110
9111TEST_F_WITH_FLAGS(
9112 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
9113 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9114 rate_limit_user_activity_poke_in_dispatcher))) {
9115 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
9116
9117 // First event of type TOUCH. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009118 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009119 milliseconds_to_nanoseconds(50));
9120 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009121 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
9122 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009123
9124 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009125 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009126 milliseconds_to_nanoseconds(130));
9127 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009128 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
9129 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009130
9131 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009132 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9133 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009134 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009135 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
9136 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009137
9138 // Within 50ns of previous TOUCH event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009139 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009140 milliseconds_to_nanoseconds(140));
9141 mFakePolicy->assertUserActivityNotPoked();
9142
9143 // Within 50ns of previous OTHER event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009144 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9145 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009146 mFakePolicy->assertUserActivityNotPoked();
9147
9148 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
9149 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009150 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009151 milliseconds_to_nanoseconds(160));
9152 mFakePolicy->assertUserActivityNotPoked();
9153
9154 // 65ns > 50ns has passed since previous OTHER event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009155 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9156 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009157 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009158 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
9159 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009160
9161 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009162 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009163 milliseconds_to_nanoseconds(300));
9164 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009165 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
9166 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009167
9168 // Assert that there's no more user activity poke event.
9169 mFakePolicy->assertUserActivityNotPoked();
9170}
9171
9172TEST_F_WITH_FLAGS(
9173 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
9174 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9175 rate_limit_user_activity_poke_in_dispatcher))) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009176 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009177 milliseconds_to_nanoseconds(200));
9178 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009179 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
9180 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009181
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009182 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009183 milliseconds_to_nanoseconds(280));
9184 mFakePolicy->assertUserActivityNotPoked();
9185
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009186 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009187 milliseconds_to_nanoseconds(340));
9188 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009189 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
9190 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009191}
9192
9193TEST_F_WITH_FLAGS(
9194 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
9195 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9196 rate_limit_user_activity_poke_in_dispatcher))) {
9197 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
9198
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009199 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9200 20);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009201 mFakePolicy->assertUserActivityPoked();
9202
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009203 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9204 30);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009205 mFakePolicy->assertUserActivityPoked();
9206}
9207
chaviwfd6d3512019-03-25 13:23:49 -07009208class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009209 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07009210 InputDispatcherTest::SetUp();
9211
Chris Yea209fde2020-07-22 13:54:51 -07009212 std::shared_ptr<FakeApplicationHandle> application =
9213 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009214 mUnfocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
9215 ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009216 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07009217
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009218 mFocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
9219 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009220 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07009221
9222 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009223 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07009224 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07009225
9226 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009227 mDispatcher->onWindowInfosChanged(
9228 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009229 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009230 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07009231 }
9232
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009233 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07009234 InputDispatcherTest::TearDown();
9235
9236 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009237 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07009238 }
9239
9240protected:
9241 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009242 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07009243 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07009244};
9245
9246// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9247// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
9248// the onPointerDownOutsideFocus callback.
9249TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009251 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9252 ui::LogicalDisplayId::DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009253 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009254 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009255
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009256 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07009257 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
9258}
9259
9260// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
9261// DOWN on the window that doesn't have focus. Ensure no window received the
9262// onPointerDownOutsideFocus callback.
9263TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009264 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009265 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009266 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009267 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009268 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009269
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009270 ASSERT_TRUE(mDispatcher->waitForIdle());
9271 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009272}
9273
9274// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
9275// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
9276TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08009277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009278 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009279 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009280 mFocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009281
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009282 ASSERT_TRUE(mDispatcher->waitForIdle());
9283 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009284}
9285
9286// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9287// DOWN on the window that already has focus. Ensure no window received the
9288// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009289TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009290 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009291 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9292 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009293 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009294 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009295
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009296 ASSERT_TRUE(mDispatcher->waitForIdle());
9297 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009298}
9299
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009300// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
9301// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
9302TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
9303 const MotionEvent event =
9304 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
9305 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009306 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009307 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
9308 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009310 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009311 mUnfocusedWindow->consumeAnyMotionDown(ui::LogicalDisplayId::DEFAULT,
9312 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009313
9314 ASSERT_TRUE(mDispatcher->waitForIdle());
9315 mFakePolicy->assertOnPointerDownWasNotCalled();
9316 // Ensure that the unfocused window did not receive any FOCUS events.
9317 mUnfocusedWindow->assertNoEvents();
9318}
9319
chaviwaf87b3e2019-10-01 16:59:28 -07009320// These tests ensures we can send touch events to a single client when there are multiple input
9321// windows that point to the same client token.
9322class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
9323 virtual void SetUp() override {
9324 InputDispatcherTest::SetUp();
9325
Chris Yea209fde2020-07-22 13:54:51 -07009326 std::shared_ptr<FakeApplicationHandle> application =
9327 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009328 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009329 ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009330 mWindow1->setFrame(Rect(0, 0, 100, 100));
9331
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009332 mWindow2 = mWindow1->clone(ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009333 mWindow2->setFrame(Rect(100, 100, 200, 200));
9334
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009335 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009336 }
9337
9338protected:
9339 sp<FakeWindowHandle> mWindow1;
9340 sp<FakeWindowHandle> mWindow2;
9341
9342 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05009343 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07009344 vec2 vals = windowInfo->transform.transform(point.x, point.y);
9345 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07009346 }
9347
9348 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
9349 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009350 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009351 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009352 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009353 ASSERT_NE(nullptr, motionEvent);
9354 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07009355
9356 for (size_t i = 0; i < points.size(); i++) {
9357 float expectedX = points[i].x;
9358 float expectedY = points[i].y;
9359
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009360 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009361 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009362 << ", got " << motionEvent->getX(i);
9363 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009364 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009365 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07009366 }
9367 }
chaviw9eaa22c2020-07-01 16:21:27 -07009368
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009369 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
9370 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07009371 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009372 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009373 ui::LogicalDisplayId::DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07009374
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009375 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009376 }
chaviwaf87b3e2019-10-01 16:59:28 -07009377};
9378
9379TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
9380 // Touch Window 1
9381 PointF touchedPoint = {10, 10};
9382 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009383 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009384
9385 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009386 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009387
9388 // Touch Window 2
9389 touchedPoint = {150, 150};
9390 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009391 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009392}
9393
chaviw9eaa22c2020-07-01 16:21:27 -07009394TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
9395 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07009396 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009397 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009398
9399 // Touch Window 1
9400 PointF touchedPoint = {10, 10};
9401 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009402 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009403 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009404 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009405
9406 // Touch Window 2
9407 touchedPoint = {150, 150};
9408 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009409 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
9410 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009411
chaviw9eaa22c2020-07-01 16:21:27 -07009412 // Update the transform so rotation is set
9413 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009414 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009415 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009416 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009417}
9418
chaviw9eaa22c2020-07-01 16:21:27 -07009419TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009420 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009421 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009422
9423 // Touch Window 1
9424 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9425 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009426 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009427
9428 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009429 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
9430 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
9431 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07009432 touchedPoints.push_back(PointF{150, 150});
9433 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009434 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009435
chaviw9eaa22c2020-07-01 16:21:27 -07009436 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009437 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009438 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009439
chaviw9eaa22c2020-07-01 16:21:27 -07009440 // Update the transform so rotation is set for Window 2
9441 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009442 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009443 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009444 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009445}
9446
chaviw9eaa22c2020-07-01 16:21:27 -07009447TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009448 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009449 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009450
9451 // Touch Window 1
9452 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9453 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009454 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009455
9456 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009457 touchedPoints.push_back(PointF{150, 150});
9458 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009459
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009460 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009461
9462 // Move both windows
9463 touchedPoints = {{20, 20}, {175, 175}};
9464 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9465 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9466
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009467 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009468
chaviw9eaa22c2020-07-01 16:21:27 -07009469 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009470 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009471 expectedPoints.pop_back();
9472
9473 // Touch Window 2
9474 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009475 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009476 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009477 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009478
9479 // Move both windows
9480 touchedPoints = {{20, 20}, {175, 175}};
9481 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9482 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9483
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009484 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009485}
9486
9487TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
9488 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009489 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009490
9491 // Touch Window 1
9492 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9493 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009494 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009495
9496 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009497 touchedPoints.push_back(PointF{150, 150});
9498 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009499
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009500 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009501
9502 // Move both windows
9503 touchedPoints = {{20, 20}, {175, 175}};
9504 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9505 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9506
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009507 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009508}
9509
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009510/**
9511 * When one of the windows is slippery, the touch should not slip into the other window with the
9512 * same input channel.
9513 */
9514TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
9515 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009516 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009517
9518 // Touch down in window 1
9519 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009520 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009521 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
9522
9523 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
9524 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
9525 // getting generated.
9526 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009527 ui::LogicalDisplayId::DEFAULT, {{150, 150}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009528
9529 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
9530}
9531
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009532/**
9533 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
9534 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
9535 * that the pointer is hovering over may have a different transform.
9536 */
9537TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009538 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009539
9540 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
9542 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9543 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009544 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
9545 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009546 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009547 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9548 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9549 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009550 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009551 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009552 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
9553}
9554
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009555class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
9556 virtual void SetUp() override {
9557 InputDispatcherTest::SetUp();
9558
Chris Yea209fde2020-07-22 13:54:51 -07009559 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009560 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009561 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009562 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009563 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009564 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07009565 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009566
9567 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009568 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009569
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009570 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009571 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009572 mWindow->consumeFocusEvent(true);
9573 }
9574
9575 virtual void TearDown() override {
9576 InputDispatcherTest::TearDown();
9577 mWindow.clear();
9578 }
9579
9580protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009581 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07009582 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009583 sp<FakeWindowHandle> mWindow;
9584 static constexpr PointF WINDOW_LOCATION = {20, 20};
9585
9586 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009587 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
9588 .x(WINDOW_LOCATION.x)
9589 .y(WINDOW_LOCATION.y);
9590 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9591 .pointer(touchingPointer)
9592 .build());
9593 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9594 .pointer(touchingPointer)
9595 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009596 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009597
9598 sp<FakeWindowHandle> addSpyWindow() {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009599 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy",
9600 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009601 spy->setTrustedOverlay(true);
9602 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009603 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009604 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009605 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009606 return spy;
9607 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009608};
9609
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009610// Send a tap and respond, which should not cause an ANR.
9611TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
9612 tapOnWindow();
9613 mWindow->consumeMotionDown();
9614 mWindow->consumeMotionUp();
9615 ASSERT_TRUE(mDispatcher->waitForIdle());
9616 mFakePolicy->assertNotifyAnrWasNotCalled();
9617}
9618
9619// Send a regular key and respond, which should not cause an ANR.
9620TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009621 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009622 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009623 ASSERT_TRUE(mDispatcher->waitForIdle());
9624 mFakePolicy->assertNotifyAnrWasNotCalled();
9625}
9626
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009627TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
9628 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009629 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009630 mWindow->consumeFocusEvent(false);
9631
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009632 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009633 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9634 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
9635 CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00009636 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009637 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009638 // Key will not go to window because we have no focused window.
9639 // The 'no focused window' ANR timer should start instead.
9640
9641 // Now, the focused application goes away.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009642 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, nullptr);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009643 // The key should get dropped and there should be no ANR.
9644
9645 ASSERT_TRUE(mDispatcher->waitForIdle());
9646 mFakePolicy->assertNotifyAnrWasNotCalled();
9647}
9648
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009649// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009650// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9651// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009652TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009653 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009654 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9655 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009656
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009657 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009658 ASSERT_TRUE(sequenceNum);
9659 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009660 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009661
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009662 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009663 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009664 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009665 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009666 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009667}
9668
9669// Send a key to the app and have the app not respond right away.
9670TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
9671 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009673 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009674 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009675 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009676 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009677 ASSERT_TRUE(mDispatcher->waitForIdle());
9678}
9679
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009680// We have a focused application, but no focused window
9681TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07009682 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009683 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009684 mWindow->consumeFocusEvent(false);
9685
9686 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009688 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9689 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009690 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9691 mDispatcher->waitForIdle();
9692 mFakePolicy->assertNotifyAnrWasNotCalled();
9693
9694 // Once a focused event arrives, we get an ANR for this application
9695 // We specify the injection timeout to be smaller than the application timeout, to ensure that
9696 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009697 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009698 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9699 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT, 50ms,
Linnan Li13bf76a2024-05-05 19:18:02 +08009700 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009701 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009702 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07009703 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009704 ASSERT_TRUE(mDispatcher->waitForIdle());
9705}
9706
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009707/**
9708 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
9709 * there will not be an ANR.
9710 */
9711TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
9712 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009713 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009714 mWindow->consumeFocusEvent(false);
9715
9716 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07009717 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
9718 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009719 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
9720 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
9721
9722 // Define a valid key down event that is stale (too old).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009723 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
9724 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN,
9725 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime,
9726 eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009727
Hu Guofe3c8f12023-09-22 17:20:15 +08009728 const int32_t policyFlags =
9729 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009730
9731 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00009732 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009733 InputEventInjectionSync::WAIT_FOR_RESULT,
9734 INJECT_EVENT_TIMEOUT, policyFlags);
9735 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
9736 << "Injection should fail because the event is stale";
9737
9738 ASSERT_TRUE(mDispatcher->waitForIdle());
9739 mFakePolicy->assertNotifyAnrWasNotCalled();
9740 mWindow->assertNoEvents();
9741}
9742
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009743// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009744// Make sure that we don't notify policy twice about the same ANR.
9745TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009746 const std::chrono::duration appTimeout = 400ms;
9747 mApplication->setDispatchingTimeout(appTimeout);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009748 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009749
Vishnu Nair47074b82020-08-14 11:54:47 -07009750 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009751 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009752 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009753
9754 // Once a focused event arrives, we get an ANR for this application
9755 // We specify the injection timeout to be smaller than the application timeout, to ensure that
9756 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009757 const std::chrono::duration eventInjectionTimeout = 100ms;
9758 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009759 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009760 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9761 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT,
9762 eventInjectionTimeout,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009763 /*allowKeyRepeat=*/false);
9764 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
9765 << "result=" << ftl::enum_string(result);
9766 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
9767 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
9768 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
9769 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009770
Vishnu Naire4df8752022-09-08 09:17:55 -07009771 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009772 // ANR should not be raised again. It is up to policy to do that if it desires.
9773 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009774
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009775 // If we now get a focused window, the ANR should stop, but the policy handles that via
9776 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009777 ASSERT_TRUE(mDispatcher->waitForIdle());
9778}
9779
9780// We have a focused application, but no focused window
9781TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07009782 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009783 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009784 mWindow->consumeFocusEvent(false);
9785
9786 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009787 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009788
Vishnu Naire4df8752022-09-08 09:17:55 -07009789 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9790 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009791
9792 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009793 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009794 ASSERT_TRUE(mDispatcher->waitForIdle());
9795 mWindow->assertNoEvents();
9796}
9797
9798/**
9799 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
9800 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
9801 * If we process 1 of the events, but ANR on the second event with the same timestamp,
9802 * the ANR mechanism should still work.
9803 *
9804 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
9805 * DOWN event, while not responding on the second one.
9806 */
9807TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
9808 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009809 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009810 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009811 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9812 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009813 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009814
9815 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009816 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009817 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009818 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9819 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009820 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009821
9822 // We have now sent down and up. Let's consume first event and then ANR on the second.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009823 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009824 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009825 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009826}
9827
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009828// A spy window can receive an ANR
9829TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
9830 sp<FakeWindowHandle> spy = addSpyWindow();
9831
9832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009833 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9834 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009835 mWindow->consumeMotionDown();
9836
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009837 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009838 ASSERT_TRUE(sequenceNum);
9839 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009840 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009841
9842 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009843 spy->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009844 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009845 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009846 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009847}
9848
9849// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009850// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009851TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
9852 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009853
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009854 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009855 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
9856 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
9857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9858 injectKeyUp(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009859
9860 // Stuck on the ACTION_UP
9861 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009862 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009863
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009864 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009865 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009866 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9867 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009868
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009869 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009870 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009871 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009872 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009873 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009874}
9875
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009876// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009877// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009878TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
9879 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009880
9881 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009882 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9883 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009884
9885 mWindow->consumeMotionDown();
9886 // Stuck on the ACTION_UP
9887 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009888 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009889
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009890 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009891 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009892 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9893 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009894
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009895 mWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009896 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009897 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009898 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009899 spy->assertNoEvents();
9900}
9901
9902TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009903 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009904
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009905 FakeMonitorReceiver monitor =
9906 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009907
9908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009909 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9910 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009911
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009912 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009913 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
9914 ASSERT_TRUE(consumeSeq);
9915
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009916 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
9917 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009918
9919 monitor.finishEvent(*consumeSeq);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009920 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009921
9922 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009923 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009924}
9925
9926// If a window is unresponsive, then you get anr. if the window later catches up and starts to
9927// process events, you don't get an anr. When the window later becomes unresponsive again, you
9928// get an ANR again.
9929// 1. tap -> block on ACTION_UP -> receive ANR
9930// 2. consume all pending events (= queue becomes healthy again)
9931// 3. tap again -> block on ACTION_UP again -> receive ANR second time
9932TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
9933 tapOnWindow();
9934
9935 mWindow->consumeMotionDown();
9936 // Block on ACTION_UP
9937 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009938 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009939 mWindow->consumeMotionUp(); // Now the connection should be healthy again
9940 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009941 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009942 mWindow->assertNoEvents();
9943
9944 tapOnWindow();
9945 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009946 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009947 mWindow->consumeMotionUp();
9948
9949 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009950 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009951 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009952 mWindow->assertNoEvents();
9953}
9954
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009955// If a connection remains unresponsive for a while, make sure policy is only notified once about
9956// it.
9957TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009959 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9960 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009961
9962 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009963 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009964 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009965 // 'notifyConnectionUnresponsive' should only be called once per connection
9966 mFakePolicy->assertNotifyAnrWasNotCalled();
9967 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009968 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009969 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009970 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009971 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009972 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009973 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009974 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009975}
9976
9977/**
9978 * 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 -07009979 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009980 */
9981TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009982 // The timeouts in this test are established by relying on the fact that the "key waiting for
9983 // events timeout" is equal to 500ms.
9984 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009985 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009986 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009987
9988 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009989 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009990 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009991 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009992 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009993
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009994 // Don't finish the events yet, and send a key
9995 mDispatcher->notifyKey(
9996 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9997 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9998 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009999 // Key will not be sent to the window, yet, because the window is still processing events
10000 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010001 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010002 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010003
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010004 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010005 // if we wait long enough though, dispatcher will give up, and still send the key
10006 // to the focused window, even though we have not yet finished the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010007 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010008 mWindow->finishEvent(*downSequenceNum);
10009 mWindow->finishEvent(*upSequenceNum);
10010}
10011
10012/**
10013 * If a window is processing a motion event, and then a key event comes in, the key event should
10014 * not go to the focused window until the motion is processed.
10015 * If then a new motion comes in, then the pending key event should be going to the currently
10016 * focused window right away.
10017 */
10018TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010019 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
10020 // The timeouts in this test are established by relying on the fact that the "key waiting for
10021 // events timeout" is equal to 500ms.
10022 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010023 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010024 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010025
10026 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010027 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010028 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010029 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010030 ASSERT_TRUE(upSequenceNum);
10031 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010032 mDispatcher->notifyKey(
10033 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10034 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10035 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010036 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010037 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010038
10039 // Now tap down again. It should cause the pending key to go to the focused window right away.
10040 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010041 // Now that we tapped, we should receive the key immediately.
10042 // Since there's still room for slowness, we use 200ms, which is much less than
10043 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
10044 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
10045 ASSERT_NE(nullptr, keyEvent);
10046 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
10047 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
10048 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
10049 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010050 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
10051 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010052 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10053 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010054 mWindow->assertNoEvents();
10055}
10056
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010057/**
10058 * Send an event to the app and have the app not respond right away.
10059 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10060 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
10061 * At some point, the window becomes responsive again.
10062 * Ensure that subsequent events get dropped, and the next gesture is delivered.
10063 */
10064TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
10065 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10066 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
10067 .build());
10068
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010069 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010070 ASSERT_TRUE(sequenceNum);
10071 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10072 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10073
10074 mWindow->finishEvent(*sequenceNum);
10075 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
10076 ASSERT_TRUE(mDispatcher->waitForIdle());
10077 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10078
10079 // Now that the window is responsive, let's continue the gesture.
10080 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10081 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10082 .build());
10083
10084 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10085 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10086 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10087 .build());
10088
10089 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10090 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10091 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10092 .build());
10093 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10094 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10095 .build());
10096 // We already canceled this pointer, so the window shouldn't get any new events.
10097 mWindow->assertNoEvents();
10098
10099 // Start another one.
10100 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10101 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
10102 .build());
10103 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10104}
10105
Prabir Pradhanfc364722024-02-08 17:51:20 +000010106// Send an event to the app and have the app not respond right away. Then remove the app window.
10107// When the window is removed, the dispatcher will cancel the events for that window.
10108// So InputDispatcher will enqueue ACTION_CANCEL event as well.
10109TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
10110 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010111 AINPUT_SOURCE_TOUCHSCREEN,
10112 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010113
10114 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10115 ASSERT_TRUE(sequenceNum);
10116
10117 // Remove the window, but the input channel should remain alive.
10118 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10119
10120 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10121 // Since the window was removed, Dispatcher does not know the PID associated with the window
10122 // anymore, so the policy is notified without the PID.
10123 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
10124 /*pid=*/std::nullopt);
10125
10126 mWindow->finishEvent(*sequenceNum);
10127 // The cancellation was generated when the window was removed, along with the focus event.
10128 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010129 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010130 mWindow->consumeFocusEvent(false);
10131 ASSERT_TRUE(mDispatcher->waitForIdle());
10132 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10133}
10134
10135// Send an event to the app and have the app not respond right away. Wait for the policy to be
10136// notified of the unresponsive window, then remove the app window.
10137TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
10138 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010139 AINPUT_SOURCE_TOUCHSCREEN,
10140 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010141
10142 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10143 ASSERT_TRUE(sequenceNum);
10144 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10145 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10146
10147 // Remove the window, but the input channel should remain alive.
10148 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10149
10150 mWindow->finishEvent(*sequenceNum);
10151 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
10152 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010153 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010154 mWindow->consumeFocusEvent(false);
10155 ASSERT_TRUE(mDispatcher->waitForIdle());
10156 // Since the window was removed, Dispatcher does not know the PID associated with the window
10157 // becoming responsive, so the policy is notified without the PID.
10158 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10159}
10160
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010161class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
10162 virtual void SetUp() override {
10163 InputDispatcherTest::SetUp();
10164
Chris Yea209fde2020-07-22 13:54:51 -070010165 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010166 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010167 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010168 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010169 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010170 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010171 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010172
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010173 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010174 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010175 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010176 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010177
10178 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010179 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -070010180 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010181
10182 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010183 mDispatcher->onWindowInfosChanged(
10184 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010185 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010186 mFocusedWindow->consumeFocusEvent(true);
10187 }
10188
10189 virtual void TearDown() override {
10190 InputDispatcherTest::TearDown();
10191
10192 mUnfocusedWindow.clear();
10193 mFocusedWindow.clear();
10194 }
10195
10196protected:
Chris Yea209fde2020-07-22 13:54:51 -070010197 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010198 sp<FakeWindowHandle> mUnfocusedWindow;
10199 sp<FakeWindowHandle> mFocusedWindow;
10200 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
10201 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
10202 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
10203
10204 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
10205
10206 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
10207
10208private:
10209 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010211 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10212 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010213 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010214 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10215 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010216 }
10217};
10218
10219// If we have 2 windows that are both unresponsive, the one with the shortest timeout
10220// should be ANR'd first.
10221TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010222 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010223 injectMotionEvent(*mDispatcher,
10224 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10225 AINPUT_SOURCE_TOUCHSCREEN)
10226 .pointer(PointerBuilder(0, ToolType::FINGER)
10227 .x(FOCUSED_WINDOW_LOCATION.x)
10228 .y(FOCUSED_WINDOW_LOCATION.y))
10229 .build()));
10230 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10231 injectMotionEvent(*mDispatcher,
10232 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
10233 AINPUT_SOURCE_TOUCHSCREEN)
10234 .pointer(PointerBuilder(0, ToolType::FINGER)
10235 .x(FOCUSED_WINDOW_LOCATION.x)
10236 .y(FOCUSED_WINDOW_LOCATION.y))
10237 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010238 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010239 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010240 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010241 // We consumed all events, so no ANR
10242 ASSERT_TRUE(mDispatcher->waitForIdle());
10243 mFakePolicy->assertNotifyAnrWasNotCalled();
10244
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010246 injectMotionEvent(*mDispatcher,
10247 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10248 AINPUT_SOURCE_TOUCHSCREEN)
10249 .pointer(PointerBuilder(0, ToolType::FINGER)
10250 .x(FOCUSED_WINDOW_LOCATION.x)
10251 .y(FOCUSED_WINDOW_LOCATION.y))
10252 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010253 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010254 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010255
10256 const std::chrono::duration timeout =
10257 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010258 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010259
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010260 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010261 mFocusedWindow->consumeMotionDown();
10262 // This cancel is generated because the connection was unresponsive
10263 mFocusedWindow->consumeMotionCancel();
10264 mFocusedWindow->assertNoEvents();
10265 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010266 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010267 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10268 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010269 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010270}
10271
10272// If we have 2 windows with identical timeouts that are both unresponsive,
10273// it doesn't matter which order they should have ANR.
10274// But we should receive ANR for both.
10275TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
10276 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010277 mUnfocusedWindow->setDispatchingTimeout(
10278 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010279 mDispatcher->onWindowInfosChanged(
10280 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010281
10282 tapOnFocusedWindow();
10283 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010284 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010285 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
10286 mFocusedWindow->getDispatchingTimeout(
10287 DISPATCHING_TIMEOUT)),
10288 mFakePolicy->getUnresponsiveWindowToken(0ms)};
10289
10290 ASSERT_THAT(anrConnectionTokens,
10291 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10292 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010293
10294 ASSERT_TRUE(mDispatcher->waitForIdle());
10295 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010296
10297 mFocusedWindow->consumeMotionDown();
10298 mFocusedWindow->consumeMotionUp();
10299 mUnfocusedWindow->consumeMotionOutside();
10300
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010301 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
10302 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010303
10304 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010305 ASSERT_THAT(responsiveTokens,
10306 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10307 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010308 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010309}
10310
10311// If a window is already not responding, the second tap on the same window should be ignored.
10312// We should also log an error to account for the dropped event (not tested here).
10313// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
10314TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
10315 tapOnFocusedWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010316 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010317 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010318 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010319 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010320 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010321 ASSERT_TRUE(upEventSequenceNum);
10322 const std::chrono::duration timeout =
10323 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010324 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010325
10326 // Tap once again
10327 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010328 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010329 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10330 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010331 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010332 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010333 FOCUSED_WINDOW_LOCATION));
10334 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
10335 // valid touch target
10336 mUnfocusedWindow->assertNoEvents();
10337
10338 // Consume the first tap
10339 mFocusedWindow->finishEvent(*downEventSequenceNum);
10340 mFocusedWindow->finishEvent(*upEventSequenceNum);
10341 ASSERT_TRUE(mDispatcher->waitForIdle());
10342 // The second tap did not go to the focused window
10343 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010344 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -080010345 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10346 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010347 mFakePolicy->assertNotifyAnrWasNotCalled();
10348}
10349
10350// If you tap outside of all windows, there will not be ANR
10351TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010352 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010353 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10354 ui::LogicalDisplayId::DEFAULT, LOCATION_OUTSIDE_ALL_WINDOWS));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010355 ASSERT_TRUE(mDispatcher->waitForIdle());
10356 mFakePolicy->assertNotifyAnrWasNotCalled();
10357}
10358
10359// Since the focused window is paused, tapping on it should not produce any events
10360TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
10361 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010362 mDispatcher->onWindowInfosChanged(
10363 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010364
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010365 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010366 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10367 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010368
10369 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
10370 ASSERT_TRUE(mDispatcher->waitForIdle());
10371 // Should not ANR because the window is paused, and touches shouldn't go to it
10372 mFakePolicy->assertNotifyAnrWasNotCalled();
10373
10374 mFocusedWindow->assertNoEvents();
10375 mUnfocusedWindow->assertNoEvents();
10376}
10377
10378/**
10379 * 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 -070010380 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010381 * If a different window becomes focused at this time, the key should go to that window instead.
10382 *
10383 * Warning!!!
10384 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
10385 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010386 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010387 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
10388 *
10389 * If that value changes, this test should also change.
10390 */
10391TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
10392 // Set a long ANR timeout to prevent it from triggering
10393 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010394 mDispatcher->onWindowInfosChanged(
10395 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010396
10397 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010398 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010399 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010400 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010401 ASSERT_TRUE(upSequenceNum);
10402 // Don't finish the events yet, and send a key
10403 // Injection will succeed because we will eventually give up and send the key to the focused
10404 // window even if motions are still being processed.
10405
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010406 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010407 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10408 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010409 /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010411 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010412 // and the key remains pending, waiting for the touch events to be processed.
10413 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
10414 // under the hood.
10415 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
10416 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010417
10418 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -070010419 mFocusedWindow->setFocusable(false);
10420 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010421 mDispatcher->onWindowInfosChanged(
10422 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010423 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010424
10425 // Focus events should precede the key events
10426 mUnfocusedWindow->consumeFocusEvent(true);
10427 mFocusedWindow->consumeFocusEvent(false);
10428
10429 // Finish the tap events, which should unblock dispatcher
10430 mUnfocusedWindow->finishEvent(*downSequenceNum);
10431 mUnfocusedWindow->finishEvent(*upSequenceNum);
10432
10433 // Now that all queues are cleared and no backlog in the connections, the key event
10434 // can finally go to the newly focused "mUnfocusedWindow".
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010435 mUnfocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010436 mFocusedWindow->assertNoEvents();
10437 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010438 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010439}
10440
10441// When the touch stream is split across 2 windows, and one of them does not respond,
10442// then ANR should be raised and the touch should be canceled for the unresponsive window.
10443// The other window should not be affected by that.
10444TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
10445 // Touch Window 1
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010446 mDispatcher->notifyMotion(
10447 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10448 ui::LogicalDisplayId::DEFAULT, {FOCUSED_WINDOW_LOCATION}));
10449 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010450
10451 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +000010452 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010453 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10454 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010455 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010456
10457 const std::chrono::duration timeout =
10458 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010459 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010460
10461 mUnfocusedWindow->consumeMotionDown();
10462 mFocusedWindow->consumeMotionDown();
10463 // Focused window may or may not receive ACTION_MOVE
10464 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010465 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010466 ASSERT_TRUE(moveOrCancelSequenceNum);
10467 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
10468 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -070010469 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010470 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
10471 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
10472 mFocusedWindow->consumeMotionCancel();
10473 } else {
10474 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
10475 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010476 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010477 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10478 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010479
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010480 mUnfocusedWindow->assertNoEvents();
10481 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010482 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010483}
10484
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010485/**
10486 * If we have no focused window, and a key comes in, we start the ANR timer.
10487 * The focused application should add a focused window before the timer runs out to prevent ANR.
10488 *
10489 * If the user touches another application during this time, the key should be dropped.
10490 * Next, if a new focused window comes in, without toggling the focused application,
10491 * then no ANR should occur.
10492 *
10493 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
10494 * but in some cases the policy may not update the focused application.
10495 */
10496TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
10497 std::shared_ptr<FakeApplicationHandle> focusedApplication =
10498 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -070010499 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010500 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, focusedApplication);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010501 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
10502 mFocusedWindow->setFocusable(false);
10503
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010504 mDispatcher->onWindowInfosChanged(
10505 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010506 mFocusedWindow->consumeFocusEvent(false);
10507
10508 // Send a key. The ANR timer should start because there is no focused window.
10509 // 'focusedApplication' will get blamed if this timer completes.
10510 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010511 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010512 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10513 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010514 /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +000010515 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010516 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010517
10518 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
10519 // then the injected touches won't cause the focused event to get dropped.
10520 // The dispatcher only checks for whether the queue should be pruned upon queueing.
10521 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
10522 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
10523 // For this test, it means that the key would get delivered to the window once it becomes
10524 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010525 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010526
10527 // Touch unfocused window. This should force the pending key to get dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010528 mDispatcher->notifyMotion(
10529 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10530 ui::LogicalDisplayId::DEFAULT, {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010531
10532 // We do not consume the motion right away, because that would require dispatcher to first
10533 // process (== drop) the key event, and by that time, ANR will be raised.
10534 // Set the focused window first.
10535 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010536 mDispatcher->onWindowInfosChanged(
10537 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010538 setFocusedWindow(mFocusedWindow);
10539 mFocusedWindow->consumeFocusEvent(true);
10540 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
10541 // to another application. This could be a bug / behaviour in the policy.
10542
10543 mUnfocusedWindow->consumeMotionDown();
10544
10545 ASSERT_TRUE(mDispatcher->waitForIdle());
10546 // Should not ANR because we actually have a focused window. It was just added too slowly.
10547 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
10548}
10549
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010550/**
10551 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
10552 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
10553 * dispatcher doesn't prune pointer events incorrectly.
10554 *
10555 * This test reproduces a crash in InputDispatcher.
10556 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
10557 *
10558 * Keep the currently focused application (mApplication), and have no focused window.
10559 * We set up two additional windows:
10560 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
10561 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
10562 * window. This window is not focusable, but is touchable.
10563 *
10564 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
10565 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
10566 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
10567 *
10568 * Now, we touch "Another window". This window is owned by a different application than
10569 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
10570 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
10571 * dropping the events from its queue. Ensure that no crash occurs.
10572 *
10573 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
10574 * This does not affect the test running time.
10575 */
10576TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
10577 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
10578 std::make_shared<FakeApplicationHandle>();
10579 systemUiApplication->setDispatchingTimeout(3000ms);
10580 mFakePolicy->setStaleEventTimeout(3000ms);
10581 sp<FakeWindowHandle> navigationBar =
10582 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010583 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010584 navigationBar->setFocusable(false);
10585 navigationBar->setWatchOutsideTouch(true);
10586 navigationBar->setFrame(Rect(0, 0, 100, 100));
10587
10588 mApplication->setDispatchingTimeout(3000ms);
10589 // 'mApplication' is already focused, but we call it again here to make it explicit.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010590 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010591
10592 std::shared_ptr<FakeApplicationHandle> anotherApplication =
10593 std::make_shared<FakeApplicationHandle>();
10594 sp<FakeWindowHandle> appWindow =
10595 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010596 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010597 appWindow->setFocusable(false);
10598 appWindow->setFrame(Rect(100, 100, 200, 200));
10599
10600 mDispatcher->onWindowInfosChanged(
10601 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
10602 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
10603 mFocusedWindow->consumeFocusEvent(false);
10604
10605 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
10606 // in response.
10607 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10608 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10609 .build());
10610 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10611
10612 // Key will not be sent anywhere because we have no focused window. It will remain pending.
10613 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
10614 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010615 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10616 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010617 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010618 /*allowKeyRepeat=*/false);
10619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10620
10621 // Finish the gesture - lift up finger and inject ACTION_UP key event
10622 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10623 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10624 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010625 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0,
10626 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010627 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010628 /*allowKeyRepeat=*/false);
10629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10630 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
10631 // getting any events yet.
10632 navigationBar->assertNoEvents();
10633
10634 // Now touch "Another window". This touch is going to a different application than the one we
10635 // are waiting for (which is 'mApplication').
10636 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
10637 // trying to be injected) and to continue processing the rest of the events in the original
10638 // order.
10639 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10640 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
10641 .build());
10642 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
10643 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
10644 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10645
10646 appWindow->assertNoEvents();
10647 navigationBar->assertNoEvents();
10648}
10649
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010650// These tests ensure we cannot send touch events to a window that's positioned behind a window
10651// that has feature NO_INPUT_CHANNEL.
10652// Layout:
10653// Top (closest to user)
10654// mNoInputWindow (above all windows)
10655// mBottomWindow
10656// Bottom (furthest from user)
10657class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
10658 virtual void SetUp() override {
10659 InputDispatcherTest::SetUp();
10660
10661 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010662 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
10663 "Window without input channel",
10664 ui::LogicalDisplayId::DEFAULT,
10665 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010666 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010667 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
10668 // It's perfectly valid for this window to not have an associated input channel
10669
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010670 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010671 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010672 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
10673
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010674 mDispatcher->onWindowInfosChanged(
10675 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010676 }
10677
10678protected:
10679 std::shared_ptr<FakeApplicationHandle> mApplication;
10680 sp<FakeWindowHandle> mNoInputWindow;
10681 sp<FakeWindowHandle> mBottomWindow;
10682};
10683
10684TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
10685 PointF touchedPoint = {10, 10};
10686
Prabir Pradhan678438e2023-04-13 19:32:51 +000010687 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010688 AINPUT_SOURCE_TOUCHSCREEN,
10689 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010690
10691 mNoInputWindow->assertNoEvents();
10692 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
10693 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
10694 // and therefore should prevent mBottomWindow from receiving touches
10695 mBottomWindow->assertNoEvents();
10696}
10697
10698/**
10699 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
10700 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
10701 */
10702TEST_F(InputDispatcherMultiWindowOcclusionTests,
10703 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010704 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
10705 "Window with input channel and NO_INPUT_CHANNEL",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010706 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010707
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010708 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010709 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010710 mDispatcher->onWindowInfosChanged(
10711 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010712
10713 PointF touchedPoint = {10, 10};
10714
Prabir Pradhan678438e2023-04-13 19:32:51 +000010715 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010716 AINPUT_SOURCE_TOUCHSCREEN,
10717 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010718
10719 mNoInputWindow->assertNoEvents();
10720 mBottomWindow->assertNoEvents();
10721}
10722
Vishnu Nair958da932020-08-21 17:12:37 -070010723class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
10724protected:
10725 std::shared_ptr<FakeApplicationHandle> mApp;
10726 sp<FakeWindowHandle> mWindow;
10727 sp<FakeWindowHandle> mMirror;
10728
10729 virtual void SetUp() override {
10730 InputDispatcherTest::SetUp();
10731 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010732 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
10733 ui::LogicalDisplayId::DEFAULT);
10734 mMirror = mWindow->clone(ui::LogicalDisplayId::DEFAULT);
10735 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Vishnu Nair958da932020-08-21 17:12:37 -070010736 mWindow->setFocusable(true);
10737 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010738 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010739 }
10740};
10741
10742TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
10743 // Request focus on a mirrored window
10744 setFocusedWindow(mMirror);
10745
10746 // window gets focused
10747 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010748 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010749 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010750 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010751}
10752
10753// A focused & mirrored window remains focused only if the window and its mirror are both
10754// focusable.
10755TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
10756 setFocusedWindow(mMirror);
10757
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010758 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -070010759 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010761 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010762 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010763 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010764 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010765 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010766
10767 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010768 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010769
10770 // window loses focus since one of the windows associated with the token in not focusable
10771 mWindow->consumeFocusEvent(false);
10772
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010773 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010774 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010775 mWindow->assertNoEvents();
10776}
10777
10778// A focused & mirrored window remains focused until the window and its mirror both become
10779// invisible.
10780TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
10781 setFocusedWindow(mMirror);
10782
10783 // window gets focused
10784 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010786 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010787 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010789 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010790 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010791
10792 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010793 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010794
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010795 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010796 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010797 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010799 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010800 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010801
10802 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010803 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010804
10805 // window loses focus only after all windows associated with the token become invisible.
10806 mWindow->consumeFocusEvent(false);
10807
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010808 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010809 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010810 mWindow->assertNoEvents();
10811}
10812
10813// A focused & mirrored window remains focused until both windows are removed.
10814TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
10815 setFocusedWindow(mMirror);
10816
10817 // window gets focused
10818 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010820 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010821 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010822 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010823 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010824 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010825
10826 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010827 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010828
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010830 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010831 mMirror->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010833 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010834 mMirror->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010835
10836 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010837 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010838 mWindow->consumeFocusEvent(false);
10839
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010840 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010841 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010842 mWindow->assertNoEvents();
10843}
10844
10845// Focus request can be pending until one window becomes visible.
10846TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
10847 // Request focus on an invisible mirror.
10848 mWindow->setVisible(false);
10849 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010850 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010851 setFocusedWindow(mMirror);
10852
10853 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010854 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010855 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010856 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -070010857
10858 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010859 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010860
10861 // window gets focused
10862 mWindow->consumeFocusEvent(true);
10863 // window gets the pending key event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010864 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -070010865}
Prabir Pradhan99987712020-11-10 18:43:05 -080010866
10867class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
10868protected:
10869 std::shared_ptr<FakeApplicationHandle> mApp;
10870 sp<FakeWindowHandle> mWindow;
10871 sp<FakeWindowHandle> mSecondWindow;
10872
10873 void SetUp() override {
10874 InputDispatcherTest::SetUp();
10875 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010876 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
10877 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080010878 mWindow->setFocusable(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010879 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
10880 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080010881 mSecondWindow->setFocusable(true);
10882
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010883 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010884 mDispatcher->onWindowInfosChanged(
10885 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -080010886
10887 setFocusedWindow(mWindow);
10888 mWindow->consumeFocusEvent(true);
10889 }
10890
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010891 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010892 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -080010893 }
10894
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010895 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
10896 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -080010897 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +090010898 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010899 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080010900 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010901 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -080010902 }
10903};
10904
10905TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
10906 // Ensure that capture cannot be obtained for unfocused windows.
10907 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
10908 mFakePolicy->assertSetPointerCaptureNotCalled();
10909 mSecondWindow->assertNoEvents();
10910
10911 // Ensure that capture can be enabled from the focus window.
10912 requestAndVerifyPointerCapture(mWindow, true);
10913
10914 // Ensure that capture cannot be disabled from a window that does not have capture.
10915 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
10916 mFakePolicy->assertSetPointerCaptureNotCalled();
10917
10918 // Ensure that capture can be disabled from the window with capture.
10919 requestAndVerifyPointerCapture(mWindow, false);
10920}
10921
10922TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010923 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080010924
10925 setFocusedWindow(mSecondWindow);
10926
10927 // Ensure that the capture disabled event was sent first.
10928 mWindow->consumeCaptureEvent(false);
10929 mWindow->consumeFocusEvent(false);
10930 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +090010931 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080010932
10933 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010934 notifyPointerCaptureChanged({});
10935 notifyPointerCaptureChanged(request);
10936 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -080010937 mWindow->assertNoEvents();
10938 mSecondWindow->assertNoEvents();
10939 mFakePolicy->assertSetPointerCaptureNotCalled();
10940}
10941
10942TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010943 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080010944
10945 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010946 notifyPointerCaptureChanged({});
10947 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080010948
10949 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +090010950 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080010951 mWindow->consumeCaptureEvent(false);
10952 mWindow->assertNoEvents();
10953}
10954
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010955TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
10956 requestAndVerifyPointerCapture(mWindow, true);
10957
10958 // The first window loses focus.
10959 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +090010960 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010961 mWindow->consumeCaptureEvent(false);
10962
10963 // Request Pointer Capture from the second window before the notification from InputReader
10964 // arrives.
10965 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090010966 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010967
10968 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010969 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010970
10971 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010972 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010973
10974 mSecondWindow->consumeFocusEvent(true);
10975 mSecondWindow->consumeCaptureEvent(true);
10976}
10977
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010978TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
10979 // App repeatedly enables and disables capture.
10980 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090010981 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010982 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090010983 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010984 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090010985 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010986
10987 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
10988 // first request is now stale, this should do nothing.
10989 notifyPointerCaptureChanged(firstRequest);
10990 mWindow->assertNoEvents();
10991
10992 // InputReader notifies that the second request was enabled.
10993 notifyPointerCaptureChanged(secondRequest);
10994 mWindow->consumeCaptureEvent(true);
10995}
10996
Prabir Pradhan7092e262022-05-03 16:51:09 +000010997TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
10998 requestAndVerifyPointerCapture(mWindow, true);
10999
11000 // App toggles pointer capture off and on.
11001 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011002 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011003
11004 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011005 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011006
11007 // InputReader notifies that the latest "enable" request was processed, while skipping over the
11008 // preceding "disable" request.
11009 notifyPointerCaptureChanged(enableRequest);
11010
11011 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
11012 // any notifications.
11013 mWindow->assertNoEvents();
11014}
11015
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011016/**
11017 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
11018 * mouse movements don't affect the previous mouse hovering state.
11019 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
11020 * HOVER_MOVE events).
11021 */
11022TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
11023 // Mouse hover on the window
11024 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11025 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11026 .build());
11027 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11028 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11029 .build());
11030
11031 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
11032 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
11033
11034 // Start pointer capture
11035 requestAndVerifyPointerCapture(mWindow, true);
11036
11037 // Send some relative mouse movements and receive them in the window.
11038 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
11039 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
11040 .build());
11041 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
11042 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
11043
11044 // Stop pointer capture
11045 requestAndVerifyPointerCapture(mWindow, false);
11046
11047 // Continue hovering on the window
11048 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11049 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
11050 .build());
11051 mWindow->consumeMotionEvent(
11052 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
11053
11054 mWindow->assertNoEvents();
11055}
11056
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011057TEST_F(InputDispatcherPointerCaptureTests, MultiDisplayPointerCapture) {
11058 // The default display is the focused display to begin with.
11059 requestAndVerifyPointerCapture(mWindow, true);
11060
11061 // Move the second window to a second display, make it the focused window on that display.
11062 mSecondWindow->editInfo()->displayId = SECOND_DISPLAY_ID;
11063 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11064 setFocusedWindow(mSecondWindow);
11065 mSecondWindow->consumeFocusEvent(true);
11066
11067 mWindow->assertNoEvents();
11068
11069 // The second window cannot gain capture because it is not on the focused display.
11070 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11071 mFakePolicy->assertSetPointerCaptureNotCalled();
11072 mSecondWindow->assertNoEvents();
11073
11074 // Make the second display the focused display.
11075 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
11076
11077 // This causes the first window to lose pointer capture, and it's unable to request capture.
11078 mWindow->consumeCaptureEvent(false);
11079 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11080
11081 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11082 mFakePolicy->assertSetPointerCaptureNotCalled();
11083
11084 // The second window is now able to gain pointer capture successfully.
11085 requestAndVerifyPointerCapture(mSecondWindow, true);
11086}
11087
Hiroki Sato25040232024-02-22 17:21:22 +090011088using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
11089
11090TEST_F(InputDispatcherPointerCaptureDeathTest,
11091 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
11092 testing::GTEST_FLAG(death_test_style) = "threadsafe";
11093 ScopedSilentDeath _silentDeath;
11094
11095 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11096 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11097
11098 // Dispatch a pointer changed event with a wrong token.
11099 request.window = mSecondWindow->getToken();
11100 ASSERT_DEATH(
11101 {
11102 notifyPointerCaptureChanged(request);
11103 mSecondWindow->consumeCaptureEvent(true);
11104 },
11105 "Unexpected requested window for Pointer Capture.");
11106}
11107
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011108class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
11109protected:
11110 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000011111
11112 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
11113 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
11114
11115 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
11116 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11117
11118 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
11119 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
11120 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11121 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
11122 MAXIMUM_OBSCURING_OPACITY);
11123
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011124 static constexpr gui::Uid TOUCHED_APP_UID{10001};
11125 static constexpr gui::Uid APP_B_UID{10002};
11126 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011127
11128 sp<FakeWindowHandle> mTouchWindow;
11129
11130 virtual void SetUp() override {
11131 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011132 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011133 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
11134 }
11135
11136 virtual void TearDown() override {
11137 InputDispatcherTest::TearDown();
11138 mTouchWindow.clear();
11139 }
11140
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011141 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050011142 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011143 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011144 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011145 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011146 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011147 return window;
11148 }
11149
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011150 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011151 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
11152 sp<FakeWindowHandle> window =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011153 sp<FakeWindowHandle>::make(app, mDispatcher, name, ui::LogicalDisplayId::DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011154 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011155 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011156 return window;
11157 }
11158
11159 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011160 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011161 AINPUT_SOURCE_TOUCHSCREEN,
11162 ui::LogicalDisplayId::DEFAULT, points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011163 }
11164};
11165
11166TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011167 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011168 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011169 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011170
11171 touch();
11172
11173 mTouchWindow->assertNoEvents();
11174}
11175
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011176TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000011177 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
11178 const sp<FakeWindowHandle>& w =
11179 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011180 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011181
11182 touch();
11183
11184 mTouchWindow->assertNoEvents();
11185}
11186
11187TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011188 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
11189 const sp<FakeWindowHandle>& w =
11190 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011191 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011192
11193 touch();
11194
11195 w->assertNoEvents();
11196}
11197
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011198TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011199 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011200 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011201
11202 touch();
11203
11204 mTouchWindow->consumeAnyMotionDown();
11205}
11206
11207TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011208 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011209 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011210 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011211 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011212
11213 touch({PointF{100, 100}});
11214
11215 mTouchWindow->consumeAnyMotionDown();
11216}
11217
11218TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011219 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011220 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011221 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011222
11223 touch();
11224
11225 mTouchWindow->consumeAnyMotionDown();
11226}
11227
11228TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
11229 const sp<FakeWindowHandle>& w =
11230 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011231 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011232
11233 touch();
11234
11235 mTouchWindow->consumeAnyMotionDown();
11236}
11237
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011238TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
11239 const sp<FakeWindowHandle>& w =
11240 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011241 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011242
11243 touch();
11244
11245 w->assertNoEvents();
11246}
11247
11248/**
11249 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
11250 * inside) while letting them pass-through. Note that even though touch passes through the occluding
11251 * window, the occluding window will still receive ACTION_OUTSIDE event.
11252 */
11253TEST_F(InputDispatcherUntrustedTouchesTest,
11254 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
11255 const sp<FakeWindowHandle>& w =
11256 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011257 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011258 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011259
11260 touch();
11261
11262 w->consumeMotionOutside();
11263}
11264
11265TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
11266 const sp<FakeWindowHandle>& w =
11267 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011268 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011269 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011270
11271 touch();
11272
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011273 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011274}
11275
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011276TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011277 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011278 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11279 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011280 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011281
11282 touch();
11283
11284 mTouchWindow->consumeAnyMotionDown();
11285}
11286
11287TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
11288 const sp<FakeWindowHandle>& w =
11289 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11290 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011291 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011292
11293 touch();
11294
11295 mTouchWindow->consumeAnyMotionDown();
11296}
11297
11298TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011299 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011300 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11301 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011302 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011303
11304 touch();
11305
11306 mTouchWindow->assertNoEvents();
11307}
11308
11309TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
11310 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
11311 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011312 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11313 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011314 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011315 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11316 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011317 mDispatcher->onWindowInfosChanged(
11318 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011319
11320 touch();
11321
11322 mTouchWindow->assertNoEvents();
11323}
11324
11325TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
11326 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
11327 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011328 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11329 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011330 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011331 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11332 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011333 mDispatcher->onWindowInfosChanged(
11334 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011335
11336 touch();
11337
11338 mTouchWindow->consumeAnyMotionDown();
11339}
11340
11341TEST_F(InputDispatcherUntrustedTouchesTest,
11342 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
11343 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011344 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11345 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011346 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011347 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11348 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011349 mDispatcher->onWindowInfosChanged(
11350 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011351
11352 touch();
11353
11354 mTouchWindow->consumeAnyMotionDown();
11355}
11356
11357TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
11358 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011359 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11360 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011361 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011362 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11363 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011364 mDispatcher->onWindowInfosChanged(
11365 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011366
11367 touch();
11368
11369 mTouchWindow->assertNoEvents();
11370}
11371
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011372TEST_F(InputDispatcherUntrustedTouchesTest,
11373 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
11374 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011375 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11376 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011377 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011378 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11379 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011380 mDispatcher->onWindowInfosChanged(
11381 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011382
11383 touch();
11384
11385 mTouchWindow->assertNoEvents();
11386}
11387
11388TEST_F(InputDispatcherUntrustedTouchesTest,
11389 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
11390 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011391 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11392 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011393 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011394 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11395 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011396 mDispatcher->onWindowInfosChanged(
11397 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011398
11399 touch();
11400
11401 mTouchWindow->consumeAnyMotionDown();
11402}
11403
11404TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
11405 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011406 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11407 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011408 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011409
11410 touch();
11411
11412 mTouchWindow->consumeAnyMotionDown();
11413}
11414
11415TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
11416 const sp<FakeWindowHandle>& w =
11417 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011418 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011419
11420 touch();
11421
11422 mTouchWindow->consumeAnyMotionDown();
11423}
11424
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011425TEST_F(InputDispatcherUntrustedTouchesTest,
11426 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
11427 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11428 const sp<FakeWindowHandle>& w =
11429 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011430 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011431
11432 touch();
11433
11434 mTouchWindow->assertNoEvents();
11435}
11436
11437TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
11438 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11439 const sp<FakeWindowHandle>& w =
11440 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011441 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011442
11443 touch();
11444
11445 mTouchWindow->consumeAnyMotionDown();
11446}
11447
11448TEST_F(InputDispatcherUntrustedTouchesTest,
11449 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
11450 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
11451 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011452 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11453 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011454 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011455
11456 touch();
11457
11458 mTouchWindow->consumeAnyMotionDown();
11459}
11460
11461TEST_F(InputDispatcherUntrustedTouchesTest,
11462 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
11463 const sp<FakeWindowHandle>& w1 =
11464 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11465 OPACITY_BELOW_THRESHOLD);
11466 const sp<FakeWindowHandle>& w2 =
11467 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11468 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011469 mDispatcher->onWindowInfosChanged(
11470 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011471
11472 touch();
11473
11474 mTouchWindow->assertNoEvents();
11475}
11476
11477/**
11478 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
11479 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
11480 * (which alone would result in allowing touches) does not affect the blocking behavior.
11481 */
11482TEST_F(InputDispatcherUntrustedTouchesTest,
11483 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
11484 const sp<FakeWindowHandle>& wB =
11485 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11486 OPACITY_BELOW_THRESHOLD);
11487 const sp<FakeWindowHandle>& wC =
11488 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11489 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011490 mDispatcher->onWindowInfosChanged(
11491 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011492
11493 touch();
11494
11495 mTouchWindow->assertNoEvents();
11496}
11497
11498/**
11499 * This test is testing that a window from a different UID but with same application token doesn't
11500 * block the touch. Apps can share the application token for close UI collaboration for example.
11501 */
11502TEST_F(InputDispatcherUntrustedTouchesTest,
11503 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
11504 const sp<FakeWindowHandle>& w =
11505 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
11506 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011507 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011508
11509 touch();
11510
11511 mTouchWindow->consumeAnyMotionDown();
11512}
11513
arthurhungb89ccb02020-12-30 16:19:01 +080011514class InputDispatcherDragTests : public InputDispatcherTest {
11515protected:
11516 std::shared_ptr<FakeApplicationHandle> mApp;
11517 sp<FakeWindowHandle> mWindow;
11518 sp<FakeWindowHandle> mSecondWindow;
11519 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011520 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011521 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
11522 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080011523
11524 void SetUp() override {
11525 InputDispatcherTest::SetUp();
11526 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011527 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11528 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011529 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011530
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011531 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11532 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011533 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011534
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011535 mSpyWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow",
11536 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011537 mSpyWindow->setSpy(true);
11538 mSpyWindow->setTrustedOverlay(true);
11539 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
11540
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011541 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011542 mDispatcher->onWindowInfosChanged(
11543 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
11544 {},
11545 0,
11546 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011547 }
11548
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011549 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
11550 switch (fromSource) {
11551 case AINPUT_SOURCE_TOUCHSCREEN:
11552 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011553 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011554 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011555 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11556 break;
11557 case AINPUT_SOURCE_STYLUS:
11558 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011559 injectMotionEvent(*mDispatcher,
11560 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11561 AINPUT_SOURCE_STYLUS)
11562 .buttonState(
11563 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
11564 .pointer(PointerBuilder(0, ToolType::STYLUS)
11565 .x(50)
11566 .y(50))
11567 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011568 break;
11569 case AINPUT_SOURCE_MOUSE:
11570 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011571 injectMotionEvent(*mDispatcher,
11572 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11573 AINPUT_SOURCE_MOUSE)
11574 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
11575 .pointer(PointerBuilder(MOUSE_POINTER_ID,
11576 ToolType::MOUSE)
11577 .x(50)
11578 .y(50))
11579 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011580 break;
11581 default:
11582 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
11583 }
arthurhungb89ccb02020-12-30 16:19:01 +080011584
11585 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011586 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011587 // Spy window should also receive motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011588 mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011589 }
11590
11591 // Start performing drag, we will create a drag window and transfer touch to it.
11592 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
11593 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011594 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000011595 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011596 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000011597 }
arthurhungb89ccb02020-12-30 16:19:01 +080011598
11599 // The drag window covers the entire display
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011600 mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow",
11601 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011602 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011603 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
11604 *mWindow->getInfo(), *mSecondWindow->getInfo()},
11605 {},
11606 0,
11607 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011608
11609 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000011610 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000011611 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
11612 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000011613 if (transferred) {
11614 mWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011615 mDragWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
11616 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000011617 }
11618 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080011619 }
11620};
11621
11622TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011623 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080011624
11625 // Move on window.
11626 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011627 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011628 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011629 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011630 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11631 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011632 mWindow->consumeDragEvent(false, 50, 50);
11633 mSecondWindow->assertNoEvents();
11634
11635 // Move to another window.
11636 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011637 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011638 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011639 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011640 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11641 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011642 mWindow->consumeDragEvent(true, 150, 50);
11643 mSecondWindow->consumeDragEvent(false, 50, 50);
11644
11645 // Move back to original window.
11646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011647 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011648 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011649 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011650 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11651 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011652 mWindow->consumeDragEvent(false, 50, 50);
11653 mSecondWindow->consumeDragEvent(true, -50, 50);
11654
11655 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011656 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011657 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011658 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011659 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011660 mWindow->assertNoEvents();
11661 mSecondWindow->assertNoEvents();
11662}
11663
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011664TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011665 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011666
11667 // No cancel event after drag start
11668 mSpyWindow->assertNoEvents();
11669
11670 const MotionEvent secondFingerDownEvent =
11671 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11672 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011673 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11674 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011675 .build();
11676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011677 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011678 InputEventInjectionSync::WAIT_FOR_RESULT))
11679 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11680
11681 // Receives cancel for first pointer after next pointer down
11682 mSpyWindow->consumeMotionCancel();
11683 mSpyWindow->consumeMotionDown();
11684
11685 mSpyWindow->assertNoEvents();
11686}
11687
arthurhungf452d0b2021-01-06 00:19:52 +080011688TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011689 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080011690
11691 // Move on window.
11692 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011693 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011694 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080011695 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011696 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11697 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080011698 mWindow->consumeDragEvent(false, 50, 50);
11699 mSecondWindow->assertNoEvents();
11700
11701 // Move to another window.
11702 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011703 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011704 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080011705 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011706 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11707 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080011708 mWindow->consumeDragEvent(true, 150, 50);
11709 mSecondWindow->consumeDragEvent(false, 50, 50);
11710
11711 // drop to another window.
11712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011713 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080011714 {150, 50}))
11715 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011716 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011717 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080011718 mWindow->assertNoEvents();
11719 mSecondWindow->assertNoEvents();
11720}
11721
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011722TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
11723 startDrag();
11724
11725 // No cancel event after drag start
11726 mSpyWindow->assertNoEvents();
11727
11728 const MotionEvent secondFingerDownEvent =
11729 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11730 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
11731 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11732 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
11733 .build();
11734 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11735 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
11736 InputEventInjectionSync::WAIT_FOR_RESULT))
11737 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11738
11739 // Receives cancel for first pointer after next pointer down
11740 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080011741 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011742 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
11743
11744 mSpyWindow->assertNoEvents();
11745
11746 // Spy window calls pilfer pointers
11747 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
11748 mDragWindow->assertNoEvents();
11749
11750 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080011751 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011752 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
11753 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
11754 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
11755 .build();
11756 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080011757 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011758 InputEventInjectionSync::WAIT_FOR_RESULT))
11759 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11760
11761 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000011762 mDragWindow->consumeMotionEvent(
11763 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011764 mDragWindow->assertNoEvents();
11765}
11766
arthurhung6d4bed92021-03-17 11:59:33 +080011767TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011768 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080011769
11770 // Move on window and keep button pressed.
11771 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011772 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011773 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11774 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011775 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011776 .build()))
11777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011778 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11779 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011780 mWindow->consumeDragEvent(false, 50, 50);
11781 mSecondWindow->assertNoEvents();
11782
11783 // Move to another window and release button, expect to drop item.
11784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011785 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011786 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11787 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011788 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011789 .build()))
11790 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011791 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11792 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011793 mWindow->assertNoEvents();
11794 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011795 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080011796
11797 // nothing to the window.
11798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011799 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011800 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
11801 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011802 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011803 .build()))
11804 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011805 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011806 mWindow->assertNoEvents();
11807 mSecondWindow->assertNoEvents();
11808}
11809
Arthur Hung54745652022-04-20 07:17:41 +000011810TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011811 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080011812
11813 // Set second window invisible.
11814 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011815 mDispatcher->onWindowInfosChanged(
11816 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080011817
11818 // Move on window.
11819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011820 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011821 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080011822 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011823 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11824 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011825 mWindow->consumeDragEvent(false, 50, 50);
11826 mSecondWindow->assertNoEvents();
11827
11828 // Move to another window.
11829 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011830 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011831 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080011832 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011833 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11834 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011835 mWindow->consumeDragEvent(true, 150, 50);
11836 mSecondWindow->assertNoEvents();
11837
11838 // drop to another window.
11839 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011840 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080011841 {150, 50}))
11842 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011843 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011844 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011845 mWindow->assertNoEvents();
11846 mSecondWindow->assertNoEvents();
11847}
11848
Arthur Hung54745652022-04-20 07:17:41 +000011849TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011850 // Ensure window could track pointerIds if it didn't support split touch.
11851 mWindow->setPreventSplitting(true);
11852
Arthur Hung54745652022-04-20 07:17:41 +000011853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011854 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11855 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000011856 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011857 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011858
11859 const MotionEvent secondFingerDownEvent =
11860 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011861 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000011862 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011863 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11864 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000011865 .build();
11866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011867 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000011868 InputEventInjectionSync::WAIT_FOR_RESULT))
11869 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011870 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000011871
11872 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011873 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000011874}
11875
11876TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
11877 // First down on second window.
11878 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011879 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11880 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000011881 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11882
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011883 mSecondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011884
11885 // Second down on first window.
11886 const MotionEvent secondFingerDownEvent =
11887 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011888 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000011889 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011890 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
11891 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000011892 .build();
11893 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011894 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000011895 InputEventInjectionSync::WAIT_FOR_RESULT))
11896 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011897 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
11898 mSecondWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011899
11900 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011901 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000011902
11903 // Move on window.
11904 const MotionEvent secondFingerMoveEvent =
11905 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11906 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011907 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
11908 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000011909 .build();
11910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011911 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000011912 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011913 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11914 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000011915 mWindow->consumeDragEvent(false, 50, 50);
11916 mSecondWindow->consumeMotionMove();
11917
11918 // Release the drag pointer should perform drop.
11919 const MotionEvent secondFingerUpEvent =
11920 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11921 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011922 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
11923 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000011924 .build();
11925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011926 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000011927 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011928 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011929 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000011930 mWindow->assertNoEvents();
11931 mSecondWindow->consumeMotionMove();
11932}
11933
Arthur Hung3915c1f2022-05-31 07:17:17 +000011934TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011935 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000011936
11937 // Update window of second display.
11938 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011939 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011940 mDispatcher->onWindowInfosChanged(
11941 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
11942 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
11943 {},
11944 0,
11945 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000011946
11947 // Let second display has a touch state.
11948 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011949 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000011950 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11951 AINPUT_SOURCE_TOUCHSCREEN)
11952 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011953 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000011954 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000011955 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000011956 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011957 mDispatcher->onWindowInfosChanged(
11958 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
11959 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
11960 {},
11961 0,
11962 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000011963
11964 // Move on window.
11965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011966 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011967 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000011968 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011969 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11970 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000011971 mWindow->consumeDragEvent(false, 50, 50);
11972 mSecondWindow->assertNoEvents();
11973
11974 // Move to another window.
11975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011976 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011977 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000011978 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011979 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11980 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000011981 mWindow->consumeDragEvent(true, 150, 50);
11982 mSecondWindow->consumeDragEvent(false, 50, 50);
11983
11984 // drop to another window.
11985 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011986 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000011987 {150, 50}))
11988 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011989 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011990 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000011991 mWindow->assertNoEvents();
11992 mSecondWindow->assertNoEvents();
11993}
11994
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011995TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
11996 startDrag(true, AINPUT_SOURCE_MOUSE);
11997 // Move on window.
11998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011999 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012000 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12001 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012002 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012003 .x(50)
12004 .y(50))
12005 .build()))
12006 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012007 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12008 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012009 mWindow->consumeDragEvent(false, 50, 50);
12010 mSecondWindow->assertNoEvents();
12011
12012 // Move to another window.
12013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012014 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012015 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12016 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012017 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012018 .x(150)
12019 .y(50))
12020 .build()))
12021 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012022 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12023 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012024 mWindow->consumeDragEvent(true, 150, 50);
12025 mSecondWindow->consumeDragEvent(false, 50, 50);
12026
12027 // drop to another window.
12028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012029 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012030 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
12031 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012032 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012033 .x(150)
12034 .y(50))
12035 .build()))
12036 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012037 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012038 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012039 mWindow->assertNoEvents();
12040 mSecondWindow->assertNoEvents();
12041}
12042
Linnan Li5af92f92023-07-14 14:36:22 +080012043/**
12044 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
12045 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
12046 */
12047TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
12048 // Down on second window
12049 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012050 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12051 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012052 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12053
12054 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
12055 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
12056
12057 // Down on first window
12058 const MotionEvent secondFingerDownEvent =
12059 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012060 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012061 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12062 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12063 .build();
12064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12065 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12066 InputEventInjectionSync::WAIT_FOR_RESULT))
12067 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12068 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12069 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
12070 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
12071
12072 // Start drag on first window
12073 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
12074
12075 // Trigger cancel
12076 mDispatcher->cancelCurrentTouch();
12077 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012078 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +000012079 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080012080 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
12081
12082 ASSERT_TRUE(mDispatcher->waitForIdle());
12083 // The D&D finished with nullptr
12084 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
12085
12086 // Remove drag window
12087 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
12088
12089 // Inject a simple gesture, ensure dispatcher not crashed
12090 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012091 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12092 ui::LogicalDisplayId::DEFAULT, PointF{50, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012093 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12094 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12095
12096 const MotionEvent moveEvent =
12097 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012098 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012099 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12100 .build();
12101 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12102 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
12103 InputEventInjectionSync::WAIT_FOR_RESULT))
12104 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12105 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
12106
12107 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012108 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Li5af92f92023-07-14 14:36:22 +080012109 {50, 50}))
12110 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12111 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
12112}
12113
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012114TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
12115 // Start hovering over the window.
12116 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12117 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012118 ui::LogicalDisplayId::DEFAULT, {50, 50}));
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012119
12120 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12121 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12122
12123 ASSERT_FALSE(startDrag(/*sendDown=*/false))
12124 << "Drag and drop should not work with a hovering pointer";
12125}
12126
Vishnu Nair062a8672021-09-03 16:07:44 -070012127class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
12128
12129TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
12130 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012131 sp<FakeWindowHandle> window =
12132 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12133 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012134 window->setDropInput(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012135 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012136 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012137 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012138 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012139 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012140
12141 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012142 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012143 window->assertNoEvents();
12144
Prabir Pradhan678438e2023-04-13 19:32:51 +000012145 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012146 AINPUT_SOURCE_TOUCHSCREEN,
12147 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012148 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012149 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080012150 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070012151 window->assertNoEvents();
12152
12153 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012154 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012155 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012156
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012157 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12158 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012159
Prabir Pradhan678438e2023-04-13 19:32:51 +000012160 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012161 AINPUT_SOURCE_TOUCHSCREEN,
12162 ui::LogicalDisplayId::DEFAULT));
12163 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012164 window->assertNoEvents();
12165}
12166
12167TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
12168 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12169 std::make_shared<FakeApplicationHandle>();
12170 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012171 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012172 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012173 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012174 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012175 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012176 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012177 sp<FakeWindowHandle> window =
12178 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12179 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012180 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012181 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012182 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012183 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012184 mDispatcher->onWindowInfosChanged(
12185 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012186 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012187 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012188
12189 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012190 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012191 window->assertNoEvents();
12192
Prabir Pradhan678438e2023-04-13 19:32:51 +000012193 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012194 AINPUT_SOURCE_TOUCHSCREEN,
12195 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012196 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012197 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012198 window->assertNoEvents();
12199
12200 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012201 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012202 mDispatcher->onWindowInfosChanged(
12203 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012204
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012205 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12206 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012207
Prabir Pradhan678438e2023-04-13 19:32:51 +000012208 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012209 AINPUT_SOURCE_TOUCHSCREEN,
12210 ui::LogicalDisplayId::DEFAULT));
12211 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
12212 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Vishnu Nair062a8672021-09-03 16:07:44 -070012213 window->assertNoEvents();
12214}
12215
12216TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
12217 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12218 std::make_shared<FakeApplicationHandle>();
12219 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012220 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012221 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012222 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012223 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012224 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012225 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012226 sp<FakeWindowHandle> window =
12227 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12228 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012229 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012230 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012231 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012232 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012233 mDispatcher->onWindowInfosChanged(
12234 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012235 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012236 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012237
12238 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012239 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012240 window->assertNoEvents();
12241
Prabir Pradhan678438e2023-04-13 19:32:51 +000012242 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012243 AINPUT_SOURCE_TOUCHSCREEN,
12244 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012245 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012246 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012247 window->assertNoEvents();
12248
12249 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012250 mDispatcher->onWindowInfosChanged(
12251 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012252
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012253 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12254 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012255
Prabir Pradhan678438e2023-04-13 19:32:51 +000012256 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012257 AINPUT_SOURCE_TOUCHSCREEN,
12258 ui::LogicalDisplayId::DEFAULT));
12259 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012260 window->assertNoEvents();
12261}
12262
Antonio Kantekf16f2832021-09-28 04:39:20 +000012263class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
12264protected:
12265 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000012266 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012267 sp<FakeWindowHandle> mWindow;
12268 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000012269 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012270
12271 void SetUp() override {
12272 InputDispatcherTest::SetUp();
12273
12274 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000012275 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012276 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
12277 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012278 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012279 setFocusedWindow(mWindow);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012280 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
12281 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012282 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000012283 mThirdWindow =
12284 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
12285 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
12286 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012287
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012288 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012289 mDispatcher->onWindowInfosChanged(
12290 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
12291 {},
12292 0,
12293 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000012294 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012295 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012296
Antonio Kantek15beb512022-06-13 22:35:41 +000012297 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012298 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012299 WINDOW_UID, /*hasPermission=*/true,
12300 ui::LogicalDisplayId::DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070012301 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
12302 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012303 mThirdWindow->assertNoEvents();
12304 }
12305
12306 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
12307 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000012308 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000012309 SECOND_DISPLAY_ID)) {
12310 mWindow->assertNoEvents();
12311 mSecondWindow->assertNoEvents();
12312 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070012313 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000012314 }
12315
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012316 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000012317 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070012318 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012319 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012320 mWindow->consumeTouchModeEvent(inTouchMode);
12321 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012322 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000012323 }
12324};
12325
Antonio Kantek26defcf2022-02-08 01:12:27 +000012326TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012327 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000012328 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
12329 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012330 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012331}
12332
Antonio Kantek26defcf2022-02-08 01:12:27 +000012333TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
12334 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012335 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012336 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012337 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012338 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012339 ownerUid, /*hasPermission=*/false,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012340 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000012341 mWindow->assertNoEvents();
12342 mSecondWindow->assertNoEvents();
12343}
12344
12345TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
12346 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012347 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012348 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012349 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000012350 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012351 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012352}
12353
Antonio Kantekf16f2832021-09-28 04:39:20 +000012354TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012355 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000012356 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
12357 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012358 /*hasPermission=*/true,
12359 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012360 mWindow->assertNoEvents();
12361 mSecondWindow->assertNoEvents();
12362}
12363
Antonio Kantek15beb512022-06-13 22:35:41 +000012364TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
12365 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
12366 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12367 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012368 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000012369 mWindow->assertNoEvents();
12370 mSecondWindow->assertNoEvents();
12371 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
12372}
12373
Antonio Kantek48710e42022-03-24 14:19:30 -070012374TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
12375 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012377 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070012378 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012379 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Antonio Kantek48710e42022-03-24 14:19:30 -070012380
12381 // Then remove focus.
12382 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012383 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070012384
12385 // Assert that caller can switch touch mode by owning one of the last interacted window.
12386 const WindowInfo& windowInfo = *mWindow->getInfo();
12387 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12388 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012389 /*hasPermission=*/false,
12390 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070012391}
12392
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012393class InputDispatcherSpyWindowTest : public InputDispatcherTest {
12394public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012395 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012396 std::shared_ptr<FakeApplicationHandle> application =
12397 std::make_shared<FakeApplicationHandle>();
12398 std::string name = "Fake Spy ";
12399 name += std::to_string(mSpyCount++);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012400 sp<FakeWindowHandle> spy =
12401 sp<FakeWindowHandle>::make(application, mDispatcher, name.c_str(),
12402 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012403 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012404 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012405 return spy;
12406 }
12407
12408 sp<FakeWindowHandle> createForeground() {
12409 std::shared_ptr<FakeApplicationHandle> application =
12410 std::make_shared<FakeApplicationHandle>();
12411 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012412 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012413 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012414 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012415 return window;
12416 }
12417
12418private:
12419 int mSpyCount{0};
12420};
12421
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012422using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012423/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012424 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
12425 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012426TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070012427 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012428 ScopedSilentDeath _silentDeath;
12429
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012430 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012431 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012432 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012433 ".* not a trusted overlay");
12434}
12435
12436/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012437 * Input injection into a display with a spy window but no foreground windows should succeed.
12438 */
12439TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012440 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012441 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012442
12443 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012444 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12445 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012446 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012447 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012448}
12449
12450/**
12451 * Verify the order in which different input windows receive events. The touched foreground window
12452 * (if there is one) should always receive the event first. When there are multiple spy windows, the
12453 * spy windows will receive the event according to their Z-order, where the top-most spy window will
12454 * receive events before ones belows it.
12455 *
12456 * Here, we set up a scenario with four windows in the following Z order from the top:
12457 * spy1, spy2, window, spy3.
12458 * We then inject an event and verify that the foreground "window" receives it first, followed by
12459 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
12460 * window.
12461 */
12462TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
12463 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012464 auto spy1 = createSpy();
12465 auto spy2 = createSpy();
12466 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012467 mDispatcher->onWindowInfosChanged(
12468 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012469 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
12470 const size_t numChannels = channels.size();
12471
Michael Wright8e9a8562022-02-09 13:44:29 +000012472 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012473 if (!epollFd.ok()) {
12474 FAIL() << "Failed to create epoll fd";
12475 }
12476
12477 for (size_t i = 0; i < numChannels; i++) {
12478 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
12479 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
12480 FAIL() << "Failed to add fd to epoll";
12481 }
12482 }
12483
12484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012485 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12486 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012487 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12488
12489 std::vector<size_t> eventOrder;
12490 std::vector<struct epoll_event> events(numChannels);
12491 for (;;) {
12492 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
12493 (100ms).count());
12494 if (nFds < 0) {
12495 FAIL() << "Failed to call epoll_wait";
12496 }
12497 if (nFds == 0) {
12498 break; // epoll_wait timed out
12499 }
12500 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070012501 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070012502 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012503 channels[i]->consumeMotionDown();
12504 }
12505 }
12506
12507 // Verify the order in which the events were received.
12508 EXPECT_EQ(3u, eventOrder.size());
12509 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
12510 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
12511 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
12512}
12513
12514/**
12515 * A spy window using the NOT_TOUCHABLE flag does not receive events.
12516 */
12517TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
12518 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012519 auto spy = createSpy();
12520 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012521 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012522
12523 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012524 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12525 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012526 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012527 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012528 spy->assertNoEvents();
12529}
12530
12531/**
12532 * A spy window will only receive gestures that originate within its touchable region. Gestures that
12533 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
12534 * to the window.
12535 */
12536TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
12537 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012538 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012539 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012540 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012541
12542 // Inject an event outside the spy window's touchable region.
12543 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012544 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12545 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012546 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12547 window->consumeMotionDown();
12548 spy->assertNoEvents();
12549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012550 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12551 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012552 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12553 window->consumeMotionUp();
12554 spy->assertNoEvents();
12555
12556 // Inject an event inside the spy window's touchable region.
12557 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012558 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12559 ui::LogicalDisplayId::DEFAULT, {5, 10}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012560 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12561 window->consumeMotionDown();
12562 spy->consumeMotionDown();
12563}
12564
12565/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012566 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012567 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012568 */
12569TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
12570 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012571 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012572 auto spy = createSpy();
12573 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012574 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012575 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012576 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012577
12578 // Inject an event outside the spy window's frame and touchable region.
12579 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012580 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12581 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012582 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12583 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012584 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012585}
12586
12587/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012588 * Even when a spy window spans over multiple foreground windows, the spy should receive all
12589 * pointers that are down within its bounds.
12590 */
12591TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
12592 auto windowLeft = createForeground();
12593 windowLeft->setFrame({0, 0, 100, 200});
12594 auto windowRight = createForeground();
12595 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012596 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012597 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012598 mDispatcher->onWindowInfosChanged(
12599 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012600
12601 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012602 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12603 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012604 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12605 windowLeft->consumeMotionDown();
12606 spy->consumeMotionDown();
12607
12608 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012609 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012610 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012611 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12612 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012613 .build();
12614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012615 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012616 InputEventInjectionSync::WAIT_FOR_RESULT))
12617 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12618 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000012619 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012620}
12621
12622/**
12623 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
12624 * the spy should receive the second pointer with ACTION_DOWN.
12625 */
12626TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
12627 auto window = createForeground();
12628 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012629 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012630 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012631 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012632
12633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012634 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12635 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012636 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12637 window->consumeMotionDown();
12638 spyRight->assertNoEvents();
12639
12640 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012641 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012642 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012643 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12644 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012645 .build();
12646 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012647 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012648 InputEventInjectionSync::WAIT_FOR_RESULT))
12649 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000012650 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012651 spyRight->consumeMotionDown();
12652}
12653
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012654/**
12655 * The spy window should not be able to affect whether or not touches are split. Only the foreground
12656 * windows should be allowed to control split touch.
12657 */
12658TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080012659 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012660 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012661 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080012662 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012663
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012664 auto window = createForeground();
12665 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012666
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012667 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012668
12669 // First finger down, no window touched.
12670 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012671 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12672 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012673 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012674 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012675 window->assertNoEvents();
12676
12677 // Second finger down on window, the window should receive touch down.
12678 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012679 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012680 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012681 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012682 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12683 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012684 .build();
12685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012686 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012687 InputEventInjectionSync::WAIT_FOR_RESULT))
12688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12689
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012690 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000012691 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012692}
12693
12694/**
12695 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
12696 * do not receive key events.
12697 */
12698TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012699 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012700 spy->setFocusable(false);
12701
12702 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012703 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012704 setFocusedWindow(window);
12705 window->consumeFocusEvent(true);
12706
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012708 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012709 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012710
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012711 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012712 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012713 window->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012714
12715 spy->assertNoEvents();
12716}
12717
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012718using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
12719
12720/**
12721 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
12722 * are currently sent to any other windows - including other spy windows - will also be cancelled.
12723 */
12724TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
12725 auto window = createForeground();
12726 auto spy1 = createSpy();
12727 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012728 mDispatcher->onWindowInfosChanged(
12729 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012730
12731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012732 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12733 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012734 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12735 window->consumeMotionDown();
12736 spy1->consumeMotionDown();
12737 spy2->consumeMotionDown();
12738
12739 // Pilfer pointers from the second spy window.
12740 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
12741 spy2->assertNoEvents();
12742 spy1->consumeMotionCancel();
12743 window->consumeMotionCancel();
12744
12745 // The rest of the gesture should only be sent to the second spy window.
12746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012747 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012748 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012749 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12750 spy2->consumeMotionMove();
12751 spy1->assertNoEvents();
12752 window->assertNoEvents();
12753}
12754
12755/**
12756 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
12757 * in the middle of the gesture.
12758 */
12759TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
12760 auto window = createForeground();
12761 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012762 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012763
12764 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012765 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12766 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012767 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012768 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12769 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012770
12771 window->releaseChannel();
12772
12773 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
12774
12775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012776 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12777 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012778 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012779 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012780}
12781
12782/**
12783 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
12784 * the spy, but not to any other windows.
12785 */
12786TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
12787 auto spy = createSpy();
12788 auto window = createForeground();
12789
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012790 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012791
12792 // First finger down on the window and the spy.
12793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012794 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12795 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012796 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12797 spy->consumeMotionDown();
12798 window->consumeMotionDown();
12799
12800 // Spy window pilfers the pointers.
12801 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
12802 window->consumeMotionCancel();
12803
12804 // Second finger down on the window and spy, but the window should not receive the pointer down.
12805 const MotionEvent secondFingerDownEvent =
12806 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012807 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012808 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012809 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12810 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012811 .build();
12812 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012813 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012814 InputEventInjectionSync::WAIT_FOR_RESULT))
12815 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12816
Harry Cutts33476232023-01-30 19:57:29 +000012817 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012818
12819 // Third finger goes down outside all windows, so injection should fail.
12820 const MotionEvent thirdFingerDownEvent =
12821 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012822 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012823 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012824 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12825 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12826 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012827 .build();
12828 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012829 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012830 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080012831 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012832
12833 spy->assertNoEvents();
12834 window->assertNoEvents();
12835}
12836
12837/**
12838 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
12839 */
12840TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
12841 auto spy = createSpy();
12842 spy->setFrame(Rect(0, 0, 100, 100));
12843 auto window = createForeground();
12844 window->setFrame(Rect(0, 0, 200, 200));
12845
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012846 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012847
12848 // First finger down on the window only
12849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012850 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12851 ui::LogicalDisplayId::DEFAULT, {150, 150}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012852 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12853 window->consumeMotionDown();
12854
12855 // Second finger down on the spy and window
12856 const MotionEvent secondFingerDownEvent =
12857 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012858 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012859 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012860 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
12861 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012862 .build();
12863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012864 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012865 InputEventInjectionSync::WAIT_FOR_RESULT))
12866 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12867 spy->consumeMotionDown();
12868 window->consumeMotionPointerDown(1);
12869
12870 // Third finger down on the spy and window
12871 const MotionEvent thirdFingerDownEvent =
12872 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012873 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012874 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012875 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
12876 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
12877 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012878 .build();
12879 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012880 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012881 InputEventInjectionSync::WAIT_FOR_RESULT))
12882 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12883 spy->consumeMotionPointerDown(1);
12884 window->consumeMotionPointerDown(2);
12885
12886 // Spy window pilfers the pointers.
12887 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012888 window->consumeMotionPointerUp(/*idx=*/2, ui::LogicalDisplayId::DEFAULT,
12889 AMOTION_EVENT_FLAG_CANCELED);
12890 window->consumeMotionPointerUp(/*idx=*/1, ui::LogicalDisplayId::DEFAULT,
12891 AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012892
12893 spy->assertNoEvents();
12894 window->assertNoEvents();
12895}
12896
12897/**
12898 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
12899 * other windows should be canceled. If this results in the cancellation of all pointers for some
12900 * window, then that window should receive ACTION_CANCEL.
12901 */
12902TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
12903 auto spy = createSpy();
12904 spy->setFrame(Rect(0, 0, 100, 100));
12905 auto window = createForeground();
12906 window->setFrame(Rect(0, 0, 200, 200));
12907
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012908 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012909
12910 // First finger down on both spy and window
12911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012912 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12913 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12915 window->consumeMotionDown();
12916 spy->consumeMotionDown();
12917
12918 // Second finger down on the spy and window
12919 const MotionEvent secondFingerDownEvent =
12920 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012921 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012922 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012923 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
12924 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012925 .build();
12926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012927 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012928 InputEventInjectionSync::WAIT_FOR_RESULT))
12929 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12930 spy->consumeMotionPointerDown(1);
12931 window->consumeMotionPointerDown(1);
12932
12933 // Spy window pilfers the pointers.
12934 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
12935 window->consumeMotionCancel();
12936
12937 spy->assertNoEvents();
12938 window->assertNoEvents();
12939}
12940
12941/**
12942 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
12943 * be sent to other windows
12944 */
12945TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
12946 auto spy = createSpy();
12947 spy->setFrame(Rect(0, 0, 100, 100));
12948 auto window = createForeground();
12949 window->setFrame(Rect(0, 0, 200, 200));
12950
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012951 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012952
12953 // First finger down on both window and spy
12954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012955 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12956 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012957 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12958 window->consumeMotionDown();
12959 spy->consumeMotionDown();
12960
12961 // Spy window pilfers the pointers.
12962 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
12963 window->consumeMotionCancel();
12964
12965 // Second finger down on the window only
12966 const MotionEvent secondFingerDownEvent =
12967 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012968 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012969 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012970 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
12971 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012972 .build();
12973 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012974 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012975 InputEventInjectionSync::WAIT_FOR_RESULT))
12976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12977 window->consumeMotionDown();
12978 window->assertNoEvents();
12979
12980 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
12981 spy->consumeMotionMove();
12982 spy->assertNoEvents();
12983}
12984
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070012985/**
12986 * A window on the left and a window on the right. Also, a spy window that's above all of the
12987 * windows, and spanning both left and right windows.
12988 * Send simultaneous motion streams from two different devices, one to the left window, and another
12989 * to the right window.
12990 * Pilfer from spy window.
12991 * Check that the pilfering only affects the pointers that are actually being received by the spy.
12992 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070012993TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer_legacy) {
12994 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070012995 sp<FakeWindowHandle> spy = createSpy();
12996 spy->setFrame(Rect(0, 0, 200, 200));
12997 sp<FakeWindowHandle> leftWindow = createForeground();
12998 leftWindow->setFrame(Rect(0, 0, 100, 100));
12999
13000 sp<FakeWindowHandle> rightWindow = createForeground();
13001 rightWindow->setFrame(Rect(100, 0, 200, 100));
13002
13003 constexpr int32_t stylusDeviceId = 1;
13004 constexpr int32_t touchDeviceId = 2;
13005
13006 mDispatcher->onWindowInfosChanged(
13007 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13008
13009 // Stylus down on left window and spy
13010 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13011 .deviceId(stylusDeviceId)
13012 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13013 .build());
13014 leftWindow->consumeMotionEvent(
13015 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13016 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13017
13018 // Finger down on right window and spy - but spy already has stylus
13019 mDispatcher->notifyMotion(
13020 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13021 .deviceId(touchDeviceId)
13022 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13023 .build());
13024 rightWindow->consumeMotionEvent(
13025 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013026 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013027
13028 // Act: pilfer from spy. Spy is currently receiving touch events.
13029 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013030 leftWindow->consumeMotionEvent(
13031 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013032 rightWindow->consumeMotionEvent(
13033 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13034
13035 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
13036 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13037 .deviceId(stylusDeviceId)
13038 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13039 .build());
13040 mDispatcher->notifyMotion(
13041 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13042 .deviceId(touchDeviceId)
13043 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13044 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013045 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013046
13047 spy->assertNoEvents();
13048 leftWindow->assertNoEvents();
13049 rightWindow->assertNoEvents();
13050}
13051
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013052/**
13053 * A window on the left and a window on the right. Also, a spy window that's above all of the
13054 * windows, and spanning both left and right windows.
13055 * Send simultaneous motion streams from two different devices, one to the left window, and another
13056 * to the right window.
13057 * Pilfer from spy window.
13058 * Check that the pilfering affects all of the pointers that are actually being received by the spy.
13059 * The spy should receive both the touch and the stylus events after pilfer.
13060 */
13061TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
13062 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13063 sp<FakeWindowHandle> spy = createSpy();
13064 spy->setFrame(Rect(0, 0, 200, 200));
13065 sp<FakeWindowHandle> leftWindow = createForeground();
13066 leftWindow->setFrame(Rect(0, 0, 100, 100));
13067
13068 sp<FakeWindowHandle> rightWindow = createForeground();
13069 rightWindow->setFrame(Rect(100, 0, 200, 100));
13070
13071 constexpr int32_t stylusDeviceId = 1;
13072 constexpr int32_t touchDeviceId = 2;
13073
13074 mDispatcher->onWindowInfosChanged(
13075 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13076
13077 // Stylus down on left window and spy
13078 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13079 .deviceId(stylusDeviceId)
13080 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13081 .build());
13082 leftWindow->consumeMotionEvent(
13083 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13084 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13085
13086 // Finger down on right window and spy
13087 mDispatcher->notifyMotion(
13088 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13089 .deviceId(touchDeviceId)
13090 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13091 .build());
13092 rightWindow->consumeMotionEvent(
13093 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13094 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13095
13096 // Act: pilfer from spy. Spy is currently receiving touch events.
13097 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13098 leftWindow->consumeMotionEvent(
13099 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
13100 rightWindow->consumeMotionEvent(
13101 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13102
13103 // Continue movements from both stylus and touch. Touch and stylus will be delivered to spy
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013104 // Instead of sending the two MOVE events for each input device together, and then receiving
13105 // them both, process them one at at time. InputConsumer is always in the batching mode, which
13106 // means that the two MOVE events will be initially put into a batch. Once the events are
13107 // batched, the 'consume' call may result in any of the MOVE events to be sent first (depending
13108 // on the implementation of InputConsumer), which would mean that the order of the received
13109 // events could be different depending on whether there are 1 or 2 events pending in the
13110 // InputChannel at the time the test calls 'consume'. To make assertions simpler here, and to
13111 // avoid this confusing behaviour, send and receive each MOVE event separately.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013112 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13113 .deviceId(stylusDeviceId)
13114 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13115 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013116 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013117 mDispatcher->notifyMotion(
13118 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13119 .deviceId(touchDeviceId)
13120 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13121 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013122 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013123
13124 spy->assertNoEvents();
13125 leftWindow->assertNoEvents();
13126 rightWindow->assertNoEvents();
13127}
13128
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000013129TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
13130 auto window = createForeground();
13131 auto spy = createSpy();
13132 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13133
13134 mDispatcher->notifyMotion(
13135 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
13136 .deviceId(1)
13137 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
13138 .build());
13139 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13140 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13141
13142 // Pilfer pointers from the spy window should fail.
13143 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
13144 spy->assertNoEvents();
13145 window->assertNoEvents();
13146}
13147
Prabir Pradhand65552b2021-10-07 11:23:50 -070013148class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
13149public:
13150 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
13151 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13152 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013153 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
13154 "Stylus interceptor window",
13155 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013156 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013157 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013158 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013159 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013160 overlay->setTrustedOverlay(true);
13161
13162 std::shared_ptr<FakeApplicationHandle> application =
13163 std::make_shared<FakeApplicationHandle>();
13164 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013165 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013166 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013167 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013168 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013169
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013170 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013171 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013172 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013173 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013174 return {std::move(overlay), std::move(window)};
13175 }
13176
13177 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000013178 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070013179 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013180 ui::LogicalDisplayId::DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070013181 }
13182
13183 void sendStylusEvent(int32_t action) {
13184 NotifyMotionArgs motionArgs =
13185 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013186 ui::LogicalDisplayId::DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013187 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000013188 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013189 }
13190};
13191
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013192using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
13193
13194TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070013195 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013196 ScopedSilentDeath _silentDeath;
13197
Prabir Pradhand65552b2021-10-07 11:23:50 -070013198 auto [overlay, window] = setupStylusOverlayScenario();
13199 overlay->setTrustedOverlay(false);
13200 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013201 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
13202 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070013203 ".* not a trusted overlay");
13204}
13205
13206TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
13207 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013208 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013209
13210 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13211 overlay->consumeMotionDown();
13212 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13213 overlay->consumeMotionUp();
13214
13215 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13216 window->consumeMotionDown();
13217 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13218 window->consumeMotionUp();
13219
13220 overlay->assertNoEvents();
13221 window->assertNoEvents();
13222}
13223
13224TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
13225 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013226 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013227 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013228
13229 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13230 overlay->consumeMotionDown();
13231 window->consumeMotionDown();
13232 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13233 overlay->consumeMotionUp();
13234 window->consumeMotionUp();
13235
13236 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13237 window->consumeMotionDown();
13238 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13239 window->consumeMotionUp();
13240
13241 overlay->assertNoEvents();
13242 window->assertNoEvents();
13243}
13244
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013245/**
13246 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
13247 * The scenario is as follows:
13248 * - The stylus interceptor overlay is configured as a spy window.
13249 * - The stylus interceptor spy receives the start of a new stylus gesture.
13250 * - It pilfers pointers and then configures itself to no longer be a spy.
13251 * - The stylus interceptor continues to receive the rest of the gesture.
13252 */
13253TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
13254 auto [overlay, window] = setupStylusOverlayScenario();
13255 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013256 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013257
13258 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13259 overlay->consumeMotionDown();
13260 window->consumeMotionDown();
13261
13262 // The interceptor pilfers the pointers.
13263 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
13264 window->consumeMotionCancel();
13265
13266 // The interceptor configures itself so that it is no longer a spy.
13267 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013268 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013269
13270 // It continues to receive the rest of the stylus gesture.
13271 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
13272 overlay->consumeMotionMove();
13273 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13274 overlay->consumeMotionUp();
13275
13276 window->assertNoEvents();
13277}
13278
Prabir Pradhan5735a322022-04-11 17:23:34 +000013279struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013280 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013281 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000013282 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
13283 std::unique_ptr<InputDispatcher>& mDispatcher;
13284
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013285 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000013286 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
13287
13288 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013289 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013290 ui::LogicalDisplayId::DEFAULT, {100, 200},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013291 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
13292 AMOTION_EVENT_INVALID_CURSOR_POSITION},
13293 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
13294 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
13295 }
13296
13297 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Linnan Li13bf76a2024-05-05 19:18:02 +080013298 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013299 ui::LogicalDisplayId::INVALID,
Prabir Pradhan5735a322022-04-11 17:23:34 +000013300 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000013301 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013302 mPolicyFlags);
13303 }
13304
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013305 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000013306 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13307 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013308 sp<FakeWindowHandle> window =
13309 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, name,
13310 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013311 window->setOwnerInfo(mPid, mUid);
13312 return window;
13313 }
13314};
13315
13316using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
13317
13318TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013319 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013320 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013321 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013322
13323 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13324 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13325 window->consumeMotionDown();
13326
13327 setFocusedWindow(window);
13328 window->consumeFocusEvent(true);
13329
13330 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13331 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013332 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013333}
13334
13335TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013336 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013337 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013338 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013339
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013340 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013341 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13342 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13343
13344 setFocusedWindow(window);
13345 window->consumeFocusEvent(true);
13346
13347 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13348 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
13349 window->assertNoEvents();
13350}
13351
13352TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013353 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013354 auto window = owner.createWindow("Owned window");
13355 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013356 spy->setSpy(true);
13357 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013358 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013359
13360 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13361 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13362 spy->consumeMotionDown();
13363 window->consumeMotionDown();
13364}
13365
13366TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013367 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013368 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013369
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013370 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013371 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013372 randosSpy->setSpy(true);
13373 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013374 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013375
13376 // The event is targeted at owner's window, so injection should succeed, but the spy should
13377 // not receive the event.
13378 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13379 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13380 randosSpy->assertNoEvents();
13381 window->consumeMotionDown();
13382}
13383
13384TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013385 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013386 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013387
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013388 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013389 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013390 randosSpy->setSpy(true);
13391 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013392 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013393
13394 // A user that has injection permission can inject into any window.
13395 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013396 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013397 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan5735a322022-04-11 17:23:34 +000013398 randosSpy->consumeMotionDown();
13399 window->consumeMotionDown();
13400
13401 setFocusedWindow(randosSpy);
13402 randosSpy->consumeFocusEvent(true);
13403
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013404 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013405 randosSpy->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013406 window->assertNoEvents();
13407}
13408
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013409TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013410 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013411 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013412
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013413 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013414 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013415 randosWindow->setFrame(Rect{-10, -10, -5, -5});
13416 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013417 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013418
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013419 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000013420 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13421 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13422 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013423 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000013424}
13425
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013426using InputDispatcherPointerInWindowTest = InputDispatcherTest;
13427
13428TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
13429 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13430
13431 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013432 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013433 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013434 sp<FakeWindowHandle> right =
13435 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13436 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013437 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013438 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13439 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013440 spy->setFrame(Rect(0, 0, 200, 100));
13441 spy->setTrustedOverlay(true);
13442 spy->setSpy(true);
13443
13444 mDispatcher->onWindowInfosChanged(
13445 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13446
13447 // Hover into the left window.
13448 mDispatcher->notifyMotion(
13449 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
13450 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
13451 .build());
13452
13453 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13454 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13455
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013456 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13457 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013458 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013459 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13460 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013461 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013462 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13463 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013464 /*pointerId=*/0));
13465
13466 // Hover move to the right window.
13467 mDispatcher->notifyMotion(
13468 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
13469 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13470 .build());
13471
13472 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13473 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13474 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
13475
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013476 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13477 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013478 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013479 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13480 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013481 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013482 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13483 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013484 /*pointerId=*/0));
13485
13486 // Stop hovering.
13487 mDispatcher->notifyMotion(
13488 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
13489 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13490 .build());
13491
13492 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13493 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13494
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013495 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13496 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013497 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013498 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13499 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013500 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013501 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13502 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013503 /*pointerId=*/0));
13504}
13505
13506TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
13507 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13508
13509 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013510 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013511 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013512 sp<FakeWindowHandle> right =
13513 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13514 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013515 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013516 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13517 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013518 spy->setFrame(Rect(0, 0, 200, 100));
13519 spy->setTrustedOverlay(true);
13520 spy->setSpy(true);
13521
13522 mDispatcher->onWindowInfosChanged(
13523 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13524
13525 // First pointer down on left window.
13526 mDispatcher->notifyMotion(
13527 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13528 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13529 .build());
13530
13531 left->consumeMotionDown();
13532 spy->consumeMotionDown();
13533
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013534 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13535 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013536 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013537 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13538 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013539 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013540 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13541 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013542 /*pointerId=*/0));
13543
13544 // Second pointer down on right window.
13545 mDispatcher->notifyMotion(
13546 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13547 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13548 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13549 .build());
13550
13551 left->consumeMotionMove();
13552 right->consumeMotionDown();
13553 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
13554
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013555 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13556 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013557 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013558 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13559 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013560 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013561 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13562 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013563 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013564 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13565 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013566 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013567 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13568 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013569 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013570 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13571 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013572 /*pointerId=*/1));
13573
13574 // Second pointer up.
13575 mDispatcher->notifyMotion(
13576 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
13577 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13578 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13579 .build());
13580
13581 left->consumeMotionMove();
13582 right->consumeMotionUp();
13583 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
13584
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013585 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13586 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013587 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013588 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13589 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013590 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013591 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13592 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013593 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013594 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13595 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013596 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013597 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13598 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013599 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013600 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13601 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013602 /*pointerId=*/1));
13603
13604 // First pointer up.
13605 mDispatcher->notifyMotion(
13606 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
13607 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13608 .build());
13609
13610 left->consumeMotionUp();
13611 spy->consumeMotionUp();
13612
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013613 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13614 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013615 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013616 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13617 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013618 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013619 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13620 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013621 /*pointerId=*/0));
13622}
13623
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013624TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse_legacy) {
13625 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013626 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13627
13628 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013629 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013630 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013631 sp<FakeWindowHandle> right =
13632 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13633 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013634 right->setFrame(Rect(100, 0, 200, 100));
13635
13636 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
13637
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013638 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13639 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013640 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013641 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13642 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013643 /*pointerId=*/0));
13644
13645 // Hover move into the window.
13646 mDispatcher->notifyMotion(
13647 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13648 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
13649 .rawXCursorPosition(50)
13650 .rawYCursorPosition(50)
13651 .deviceId(DEVICE_ID)
13652 .build());
13653
13654 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13655
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013656 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13657 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013658 /*pointerId=*/0));
13659
13660 // Move the mouse with another device. This cancels the hovering pointer from the first device.
13661 mDispatcher->notifyMotion(
13662 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13663 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
13664 .rawXCursorPosition(51)
13665 .rawYCursorPosition(50)
13666 .deviceId(SECOND_DEVICE_ID)
13667 .build());
13668
13669 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13670 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13671
13672 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
13673 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013674 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13675 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013676 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013677 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013678 SECOND_DEVICE_ID,
13679 /*pointerId=*/0));
13680
13681 // Move the mouse outside the window. Document the current behavior, where the window does not
13682 // receive HOVER_EXIT even though the mouse left the window.
13683 mDispatcher->notifyMotion(
13684 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13685 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
13686 .rawXCursorPosition(150)
13687 .rawYCursorPosition(50)
13688 .deviceId(SECOND_DEVICE_ID)
13689 .build());
13690
13691 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13692 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013693 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13694 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013695 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013696 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013697 SECOND_DEVICE_ID,
13698 /*pointerId=*/0));
13699}
13700
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013701/**
13702 * TODO(b/313689709) - correctly support multiple mouse devices, because they should be controlling
13703 * the same cursor, and therefore have a shared motion event stream.
13704 */
13705TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
13706 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13707 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13708
13709 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013710 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013711 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013712 sp<FakeWindowHandle> right =
13713 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13714 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013715 right->setFrame(Rect(100, 0, 200, 100));
13716
13717 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
13718
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013719 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13720 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013721 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013722 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13723 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013724 /*pointerId=*/0));
13725
13726 // Hover move into the window.
13727 mDispatcher->notifyMotion(
13728 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13729 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
13730 .rawXCursorPosition(50)
13731 .rawYCursorPosition(50)
13732 .deviceId(DEVICE_ID)
13733 .build());
13734
13735 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13736
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013737 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13738 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013739 /*pointerId=*/0));
13740
13741 // Move the mouse with another device
13742 mDispatcher->notifyMotion(
13743 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13744 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
13745 .rawXCursorPosition(51)
13746 .rawYCursorPosition(50)
13747 .deviceId(SECOND_DEVICE_ID)
13748 .build());
13749 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13750
13751 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
13752 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013753 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13754 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013755 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013756 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013757 SECOND_DEVICE_ID,
13758 /*pointerId=*/0));
13759
13760 // Move the mouse outside the window. Document the current behavior, where the window does not
13761 // receive HOVER_EXIT even though the mouse left the window.
13762 mDispatcher->notifyMotion(
13763 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13764 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
13765 .rawXCursorPosition(150)
13766 .rawYCursorPosition(50)
13767 .deviceId(SECOND_DEVICE_ID)
13768 .build());
13769
13770 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013771 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13772 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013773 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013774 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013775 SECOND_DEVICE_ID,
13776 /*pointerId=*/0));
13777}
13778
Garfield Tane84e6f92019-08-29 17:28:41 -070013779} // namespace android::inputdispatcher