blob: 4e662d4b5e96c03b746bc89a0449f453fbfb0909 [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
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800416TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000417 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
418 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000419 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000420 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800421
422 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
423 args.policyFlags |= POLICY_FLAG_TRUSTED;
424 mFakePolicy->assertNotifySwitchWasCalled(args);
425}
426
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700427namespace {
428
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700429static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700430
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000431class FakeMonitorReceiver {
432public:
Linnan Li13bf76a2024-05-05 19:18:02 +0800433 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name,
434 ui::LogicalDisplayId displayId)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700435 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000436
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700437 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000438
Linnan Li13bf76a2024-05-05 19:18:02 +0800439 void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700440 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
441 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000442 }
443
444 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800445 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
446 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000447 }
448
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700449 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000450
Linnan Li13bf76a2024-05-05 19:18:02 +0800451 void consumeMotionDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700452 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
453 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000454 }
455
Linnan Li13bf76a2024-05-05 19:18:02 +0800456 void consumeMotionMove(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700457 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
458 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000459 }
460
Linnan Li13bf76a2024-05-05 19:18:02 +0800461 void consumeMotionUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700462 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
463 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000464 }
465
Linnan Li13bf76a2024-05-05 19:18:02 +0800466 void consumeMotionCancel(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700467 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000468 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
469 WithDisplayId(expectedDisplayId),
470 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
471 }
472
473 void consumeMotionPointerDown(int32_t pointerIdx) {
474 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
475 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700476 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700477 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000478 }
479
480 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700481 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000482 }
483
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800484 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000485
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800486 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000487
488private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700489 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000490};
491
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800492static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700493 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700494 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800495 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800496 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000497 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +0000498 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800499 KeyEvent event;
500 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
501
502 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800503 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +0000504 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
505 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800506
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800507 if (!allowKeyRepeat) {
508 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
509 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800510 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700511 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800512}
513
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700514static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
515 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700516 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
517 ui::LogicalDisplayId::INVALID, InputEventInjectionSync::WAIT_FOR_RESULT,
518 CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700519 if (result != InputEventInjectionResult::TIMED_OUT) {
520 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
521 }
522}
523
Linnan Li13bf76a2024-05-05 19:18:02 +0800524static InputEventInjectionResult injectKeyDown(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700525 InputDispatcher& dispatcher,
526 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000527 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700528}
529
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800530// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
531// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
532// has to be woken up to process the repeating key.
Linnan Li13bf76a2024-05-05 19:18:02 +0800533static InputEventInjectionResult injectKeyDownNoRepeat(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700534 InputDispatcher& dispatcher,
535 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000536 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800537 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +0000538 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800539}
540
Linnan Li13bf76a2024-05-05 19:18:02 +0800541static InputEventInjectionResult injectKeyUp(
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_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700545}
546
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800547static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700548 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -0700549 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000550 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000551 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700552 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
553 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -0700554}
555
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800556static InputEventInjectionResult injectMotionEvent(
Linnan Li13bf76a2024-05-05 19:18:02 +0800557 InputDispatcher& dispatcher, int32_t action, int32_t source, ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700558 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700559 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700560 AMOTION_EVENT_INVALID_CURSOR_POSITION},
561 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800562 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000563 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000564 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700565 MotionEventBuilder motionBuilder =
566 MotionEventBuilder(action, source)
567 .displayId(displayId)
568 .eventTime(eventTime)
569 .rawXCursorPosition(cursorPosition.x)
570 .rawYCursorPosition(cursorPosition.y)
571 .pointer(
572 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
573 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
574 motionBuilder.downTime(eventTime);
575 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800576
577 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700578 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
579 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800580}
581
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700582static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800583 ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700584 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700585 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -0700586}
587
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700588static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800589 ui::LogicalDisplayId displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800590 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700591 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +0000592}
593
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700594static NotifyKeyArgs generateKeyArgs(
595 int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Jackal Guof9696682018-10-05 12:23:23 +0800596 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
597 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000598 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
599 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
600 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800601
602 return args;
603}
604
Prabir Pradhan678438e2023-04-13 19:32:51 +0000605[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800606 ui::LogicalDisplayId displayId,
Prabir Pradhan678438e2023-04-13 19:32:51 +0000607 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -0800608 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700609 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
610 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
611 }
612
chaviwd1c23182019-12-20 18:44:56 -0800613 PointerProperties pointerProperties[pointerCount];
614 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800615
chaviwd1c23182019-12-20 18:44:56 -0800616 for (size_t i = 0; i < pointerCount; i++) {
617 pointerProperties[i].clear();
618 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -0700619 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800620
chaviwd1c23182019-12-20 18:44:56 -0800621 pointerCoords[i].clear();
622 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
623 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
624 }
Jackal Guof9696682018-10-05 12:23:23 +0800625
626 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
627 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000628 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
629 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
630 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800631 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000632 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700633 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000634 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +0800635
636 return args;
637}
638
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800639static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
640 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
641}
642
Linnan Li13bf76a2024-05-05 19:18:02 +0800643static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
644 ui::LogicalDisplayId displayId) {
chaviwd1c23182019-12-20 18:44:56 -0800645 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
646}
647
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000648static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
649 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000650 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
651 request);
Prabir Pradhan99987712020-11-10 18:43:05 -0800652}
653
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700654} // namespace
655
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800656/**
657 * When a window unexpectedly disposes of its input channel, policy should be notified about the
658 * broken channel.
659 */
660TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
661 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700662 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
663 "Window that breaks its input channel",
664 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800665
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700666 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800667
668 // Window closes its channel, but the window remains.
669 window->destroyReceiver();
670 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
671}
672
Arthur Hungb92218b2018-08-14 12:00:21 +0800673TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700674 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700675 sp<FakeWindowHandle> window =
676 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
677 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800678
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700679 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700681 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
682 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800683 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800684
685 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700686 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800687}
688
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800689using InputDispatcherDeathTest = InputDispatcherTest;
690
691/**
692 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
693 * should crash.
694 */
695TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
696 testing::GTEST_FLAG(death_test_style) = "threadsafe";
697 ScopedSilentDeath _silentDeath;
698
699 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700700 sp<FakeWindowHandle> window =
701 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
702 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800703 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
704 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
705 "Incorrect WindowInfosUpdate provided");
706}
707
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700708TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
709 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700710 sp<FakeWindowHandle> window =
711 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
712 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700713
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700714 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700715 // Inject a MotionEvent to an unknown display.
716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700717 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
718 ui::LogicalDisplayId::INVALID))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700719 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
720
721 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700722 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700723}
724
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700725/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700726 * Calling onWindowInfosChanged once should not cause any issues.
727 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700728 * called twice.
729 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -0800730TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -0700731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700732 sp<FakeWindowHandle> window =
733 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
734 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700735 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700736
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700737 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700739 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
740 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800741 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700742
743 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700744 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700745}
746
747/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700748 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700749 */
750TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700751 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700752 sp<FakeWindowHandle> window =
753 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
754 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700755 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700756
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700757 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
758 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700760 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
761 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700763
764 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700765 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700766}
767
Arthur Hungb92218b2018-08-14 12:00:21 +0800768// The foreground window should receive the first touch down event.
769TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700770 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700771 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
772 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000773 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700774 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
775 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800776
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700777 mDispatcher->onWindowInfosChanged(
778 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700780 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
781 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800782 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800783
784 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700785 windowTop->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800786 windowSecond->assertNoEvents();
787}
788
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000789/**
790 * Two windows: A top window, and a wallpaper behind the window.
791 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
792 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800793 * 1. foregroundWindow <-- dup touch to wallpaper
794 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000795 */
796TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
797 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
798 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700799 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
800 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800801 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000802 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700803 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
804 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800805 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000806
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700807 mDispatcher->onWindowInfosChanged(
808 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000809 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800810 injectMotionEvent(*mDispatcher,
811 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
812 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
813 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000814 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
815
816 // Both foreground window and its wallpaper should receive the touch down
817 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700818 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000819
820 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800821 injectMotionEvent(*mDispatcher,
822 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
823 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
824 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000825 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
826
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800827 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700828 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000829
830 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700831 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000832 foregroundWindow->consumeMotionCancel();
833 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700834 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000835}
836
837/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800838 * Two fingers down on the window, and lift off the first finger.
839 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
840 * contains a single pointer.
841 */
842TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
843 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700844 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
845 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800846
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700847 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800848 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +0000849 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
850 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
851 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800852 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000853 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
854 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
855 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
856 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800857 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000858 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
859 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
860 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
861 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800862 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
863 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
864 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
865
866 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700867 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800868 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
869 window->consumeMotionEvent(
870 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
871}
872
873/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800874 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
875 * with the following differences:
876 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
877 * clean up the connection.
878 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
879 * Ensure that there's no crash in the dispatcher.
880 */
881TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
882 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
883 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700884 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
885 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800886 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800887 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700888 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
889 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800890 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800891
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700892 mDispatcher->onWindowInfosChanged(
893 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700895 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
896 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800897 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
898
899 // Both foreground window and its wallpaper should receive the touch down
900 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700901 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800902
903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700904 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700905 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800906 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
907
908 foregroundWindow->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700909 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800910
911 // Wallpaper closes its channel, but the window remains.
912 wallpaperWindow->destroyReceiver();
913 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
914
915 // Now the foreground window goes away, but the wallpaper stays, even though its channel
916 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700917 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800918 foregroundWindow->consumeMotionCancel();
919}
920
Linnan Li72352222024-04-12 18:55:57 +0800921/**
922 * Two windows: left and right, and a separate wallpaper window underneath each. Device A sends a
923 * down event to the left window. Device B sends a down event to the right window. Next, the right
924 * window disappears. Both the right window and its wallpaper window should receive cancel event.
925 * The left window and its wallpaper window should not receive any events.
926 */
927TEST_F(InputDispatcherTest, MultiDeviceDisappearingWindowWithWallpaperWindows) {
928 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
929 sp<FakeWindowHandle> leftForegroundWindow =
930 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700931 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800932 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
933 leftForegroundWindow->setDupTouchToWallpaper(true);
934 sp<FakeWindowHandle> leftWallpaperWindow =
935 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700936 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800937 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
938 leftWallpaperWindow->setIsWallpaper(true);
939
940 sp<FakeWindowHandle> rightForegroundWindow =
941 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700942 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800943 rightForegroundWindow->setFrame(Rect(100, 0, 200, 100));
944 rightForegroundWindow->setDupTouchToWallpaper(true);
945 sp<FakeWindowHandle> rightWallpaperWindow =
946 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700947 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800948 rightWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
949 rightWallpaperWindow->setIsWallpaper(true);
950
951 mDispatcher->onWindowInfosChanged(
952 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
953 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
954 {},
955 0,
956 0});
957
958 const DeviceId deviceA = 9;
959 const DeviceId deviceB = 3;
960 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
961 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
962 .deviceId(deviceA)
963 .build());
964 leftForegroundWindow->consumeMotionEvent(
965 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
966 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
967 WithDeviceId(deviceA),
968 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
969
970 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
971 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
972 .deviceId(deviceB)
973 .build());
974 rightForegroundWindow->consumeMotionEvent(
975 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
976 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
977 WithDeviceId(deviceB),
978 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
979
980 // Now right foreground window disappears, but right wallpaper window remains.
981 mDispatcher->onWindowInfosChanged(
982 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
983 *rightWallpaperWindow->getInfo()},
984 {},
985 0,
986 0});
987
988 // Left foreground window and left wallpaper window still exist, and should not receive any
989 // events.
990 leftForegroundWindow->assertNoEvents();
991 leftWallpaperWindow->assertNoEvents();
992 // Since right foreground window disappeared, right wallpaper window and right foreground window
993 // should receive cancel events.
994 rightForegroundWindow->consumeMotionEvent(
995 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
996 rightWallpaperWindow->consumeMotionEvent(
997 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
998 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
999}
1000
1001/**
1002 * Three windows arranged horizontally and without any overlap. Every window has a
1003 * wallpaper window underneath. The middle window also has SLIPPERY flag.
1004 * Device A sends a down event to the left window. Device B sends a down event to the middle window.
1005 * Next, device B sends move event to the right window. Touch for device B should slip from the
1006 * middle window to the right window. Also, the right wallpaper window should receive a down event.
1007 * The middle window and its wallpaper window should receive a cancel event. The left window should
1008 * not receive any events. If device B continues to report events, the right window and its
1009 * wallpaper window should receive remaining events.
1010 */
1011TEST_F(InputDispatcherTest, MultiDeviceSlipperyTouchWithWallpaperWindow) {
1012 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1013 sp<FakeWindowHandle> leftForegroundWindow =
1014 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001015 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001016 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1017 leftForegroundWindow->setDupTouchToWallpaper(true);
1018 sp<FakeWindowHandle> leftWallpaperWindow =
1019 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001020 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001021 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1022 leftWallpaperWindow->setIsWallpaper(true);
1023
1024 sp<FakeWindowHandle> middleForegroundWindow =
1025 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001026 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001027 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1028 middleForegroundWindow->setDupTouchToWallpaper(true);
1029 middleForegroundWindow->setSlippery(true);
1030 sp<FakeWindowHandle> middleWallpaperWindow =
1031 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001032 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001033 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1034 middleWallpaperWindow->setIsWallpaper(true);
1035
1036 sp<FakeWindowHandle> rightForegroundWindow =
1037 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001038 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001039 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1040 rightForegroundWindow->setDupTouchToWallpaper(true);
1041 sp<FakeWindowHandle> rightWallpaperWindow =
1042 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001043 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001044 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1045 rightWallpaperWindow->setIsWallpaper(true);
1046
1047 mDispatcher->onWindowInfosChanged(
1048 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1049 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1050 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1051 {},
1052 0,
1053 0});
1054
1055 const DeviceId deviceA = 9;
1056 const DeviceId deviceB = 3;
1057 // Device A sends a DOWN event to the left window
1058 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1059 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1060 .deviceId(deviceA)
1061 .build());
1062 leftForegroundWindow->consumeMotionEvent(
1063 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1064 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1065 WithDeviceId(deviceA),
1066 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1067 // Device B sends a DOWN event to the middle window
1068 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1069 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1070 .deviceId(deviceB)
1071 .build());
1072 middleForegroundWindow->consumeMotionEvent(
1073 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1074 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1075 WithDeviceId(deviceB),
1076 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1077 // Move the events of device B to the top of the right window.
1078 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1079 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
1080 .deviceId(deviceB)
1081 .build());
1082 middleForegroundWindow->consumeMotionEvent(
1083 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1084 middleWallpaperWindow->consumeMotionEvent(
1085 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1086 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1087 rightForegroundWindow->consumeMotionEvent(
1088 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1089 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1090 WithDeviceId(deviceB),
1091 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1092 // Make sure the window on the right can receive the remaining events.
1093 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1094 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1095 .deviceId(deviceB)
1096 .build());
1097 leftForegroundWindow->assertNoEvents();
1098 leftWallpaperWindow->assertNoEvents();
1099 middleForegroundWindow->assertNoEvents();
1100 middleWallpaperWindow->assertNoEvents();
1101 rightForegroundWindow->consumeMotionEvent(
1102 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
1103 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1104 WithDeviceId(deviceB),
1105 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1106}
1107
1108/**
1109 * Similar to the test above, we have three windows, they are arranged horizontally and without any
1110 * overlap, and every window has a wallpaper window. The middle window is a simple window, without
1111 * any special flags. Device A reports a down event that lands in left window. Device B sends a down
1112 * event to the middle window and then touch is transferred from the middle window to the right
1113 * window. The right window and its wallpaper window should receive a down event. The middle window
1114 * and its wallpaper window should receive a cancel event. The left window should not receive any
1115 * events. Subsequent events reported by device B should go to the right window and its wallpaper.
1116 */
1117TEST_F(InputDispatcherTest, MultiDeviceTouchTransferWithWallpaperWindows) {
1118 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1119 sp<FakeWindowHandle> leftForegroundWindow =
1120 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001121 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001122 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1123 leftForegroundWindow->setDupTouchToWallpaper(true);
1124 sp<FakeWindowHandle> leftWallpaperWindow =
1125 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001126 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001127 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1128 leftWallpaperWindow->setIsWallpaper(true);
1129
1130 sp<FakeWindowHandle> middleForegroundWindow =
1131 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001132 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001133 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1134 middleForegroundWindow->setDupTouchToWallpaper(true);
1135 sp<FakeWindowHandle> middleWallpaperWindow =
1136 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001137 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001138 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1139 middleWallpaperWindow->setIsWallpaper(true);
1140
1141 sp<FakeWindowHandle> rightForegroundWindow =
1142 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001143 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001144 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1145 rightForegroundWindow->setDupTouchToWallpaper(true);
1146 sp<FakeWindowHandle> rightWallpaperWindow =
1147 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001148 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001149 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1150 rightWallpaperWindow->setIsWallpaper(true);
1151
1152 mDispatcher->onWindowInfosChanged(
1153 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1154 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1155 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1156 {},
1157 0,
1158 0});
1159
1160 const DeviceId deviceA = 9;
1161 const DeviceId deviceB = 3;
1162 // Device A touch down on the left window
1163 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1164 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1165 .deviceId(deviceA)
1166 .build());
1167 leftForegroundWindow->consumeMotionEvent(
1168 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1169 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1170 WithDeviceId(deviceA),
1171 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1172 // Device B touch down on the middle window
1173 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1174 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1175 .deviceId(deviceB)
1176 .build());
1177 middleForegroundWindow->consumeMotionEvent(
1178 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1179 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1180 WithDeviceId(deviceB),
1181 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1182
1183 // Transfer touch from the middle window to the right window.
1184 ASSERT_TRUE(mDispatcher->transferTouchGesture(middleForegroundWindow->getToken(),
1185 rightForegroundWindow->getToken()));
1186
1187 middleForegroundWindow->consumeMotionEvent(
1188 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1189 middleWallpaperWindow->consumeMotionEvent(
1190 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1191 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1192 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1193 WithDeviceId(deviceB),
1194 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1195 rightWallpaperWindow->consumeMotionEvent(
1196 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
1197 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1198
1199 // Make sure the right window can receive the remaining events.
1200 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1201 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1202 .deviceId(deviceB)
1203 .build());
1204 leftForegroundWindow->assertNoEvents();
1205 leftWallpaperWindow->assertNoEvents();
1206 middleForegroundWindow->assertNoEvents();
1207 middleWallpaperWindow->assertNoEvents();
1208 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1209 WithDeviceId(deviceB),
1210 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1211 rightWallpaperWindow->consumeMotionEvent(
1212 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB),
1213 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1214}
1215
Arthur Hungc539dbb2022-12-08 07:45:36 +00001216class ShouldSplitTouchFixture : public InputDispatcherTest,
1217 public ::testing::WithParamInterface<bool> {};
1218INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1219 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001220/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001221 * A single window that receives touch (on top), and a wallpaper window underneath it.
1222 * The top window gets a multitouch gesture.
1223 * Ensure that wallpaper gets the same gesture.
1224 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001225TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001226 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001227 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001228 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
1229 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001230 foregroundWindow->setDupTouchToWallpaper(true);
1231 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001232
1233 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001234 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1235 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001236 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001237
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001238 mDispatcher->onWindowInfosChanged(
1239 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001240
1241 // Touch down on top window
1242 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001243 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1244 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001245 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1246
1247 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001248 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001249 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001250
1251 // Second finger down on the top window
1252 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001253 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001254 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001255 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1256 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001257 .build();
1258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001259 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001260 InputEventInjectionSync::WAIT_FOR_RESULT))
1261 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00001262 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001263 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001264 EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001265
1266 const MotionEvent secondFingerUpEvent =
1267 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001268 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hungc539dbb2022-12-08 07:45:36 +00001269 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001270 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1271 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001272 .build();
1273 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001274 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001275 InputEventInjectionSync::WAIT_FOR_RESULT))
1276 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00001277 foregroundWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1278 WithDisplayId(ui::LogicalDisplayId::DEFAULT));
1279 wallpaperWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1280 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
1281 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
Arthur Hungc539dbb2022-12-08 07:45:36 +00001282
1283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001284 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001285 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1286 AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001287 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001288 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001289 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001290 .x(100)
1291 .y(100))
1292 .build(),
1293 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001294 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001295 foregroundWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
1296 wallpaperWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001297}
1298
1299/**
1300 * Two windows: a window on the left and window on the right.
1301 * A third window, wallpaper, is behind both windows, and spans both top windows.
1302 * The first touch down goes to the left window. A second pointer touches down on the right window.
1303 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1304 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1305 * ACTION_POINTER_DOWN(1).
1306 */
1307TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1308 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001309 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1310 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001311 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001312 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001313
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001314 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1315 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001316 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001317 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001318
1319 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001320 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1321 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001322 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001323 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001324
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001325 mDispatcher->onWindowInfosChanged(
1326 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1327 {},
1328 0,
1329 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001330
1331 // Touch down on left window
1332 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001333 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1334 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001335 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1336
1337 // Both foreground window and its wallpaper should receive the touch down
1338 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001339 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001340
1341 // Second finger down on the right window
1342 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001343 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001344 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001345 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1346 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001347 .build();
1348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001349 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001350 InputEventInjectionSync::WAIT_FOR_RESULT))
1351 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1352
1353 leftWindow->consumeMotionMove();
1354 // Since the touch is split, right window gets ACTION_DOWN
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001355 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1356 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001357 EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001358
1359 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001360 mDispatcher->onWindowInfosChanged(
1361 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001362 leftWindow->consumeMotionCancel();
1363 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001364 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001365
1366 // The pointer that's still down on the right window moves, and goes to the right window only.
1367 // As far as the dispatcher's concerned though, both pointers are still present.
1368 const MotionEvent secondFingerMoveEvent =
1369 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1370 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001371 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1372 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001373 .build();
1374 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001375 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001376 InputEventInjectionSync::WAIT_FOR_RESULT));
1377 rightWindow->consumeMotionMove();
1378
1379 leftWindow->assertNoEvents();
1380 rightWindow->assertNoEvents();
1381 wallpaperWindow->assertNoEvents();
1382}
1383
Arthur Hungc539dbb2022-12-08 07:45:36 +00001384/**
1385 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
1386 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
1387 * The right window should receive ACTION_DOWN.
1388 */
1389TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00001390 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001391 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1392 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001393 leftWindow->setFrame(Rect(0, 0, 200, 200));
1394 leftWindow->setDupTouchToWallpaper(true);
1395 leftWindow->setSlippery(true);
1396
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001397 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1398 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001399 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00001400
1401 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001402 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1403 ui::LogicalDisplayId::DEFAULT);
Arthur Hung74c248d2022-11-23 07:09:59 +00001404 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00001405
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001406 mDispatcher->onWindowInfosChanged(
1407 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1408 {},
1409 0,
1410 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00001411
Arthur Hungc539dbb2022-12-08 07:45:36 +00001412 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00001413 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001414 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1415 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001416 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00001417
1418 // Both foreground window and its wallpaper should receive the touch down
1419 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001420 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001421
Arthur Hungc539dbb2022-12-08 07:45:36 +00001422 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00001423 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001424 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001425 ui::LogicalDisplayId::DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001426 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1427
Arthur Hungc539dbb2022-12-08 07:45:36 +00001428 leftWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001429 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1430 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001431}
1432
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001433/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001434 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1435 * interactive, it might stop sending this flag.
1436 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
1437 * to have a consistent input stream.
1438 *
1439 * Test procedure:
1440 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
1441 * DOWN (new gesture).
1442 *
1443 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
1444 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
1445 *
1446 * We technically just need a single window here, but we are using two windows (spy on top and a
1447 * regular window below) to emulate the actual situation where it happens on the device.
1448 */
1449TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
1450 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001451 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
1452 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001453 spyWindow->setFrame(Rect(0, 0, 200, 200));
1454 spyWindow->setTrustedOverlay(true);
1455 spyWindow->setSpy(true);
1456
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001457 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1458 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001459 window->setFrame(Rect(0, 0, 200, 200));
1460
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001461 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001462 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001463
1464 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001465 mDispatcher->notifyMotion(
1466 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1467 .deviceId(touchDeviceId)
1468 .policyFlags(DEFAULT_POLICY_FLAGS)
1469 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1470 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001471
Prabir Pradhan678438e2023-04-13 19:32:51 +00001472 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1473 .deviceId(touchDeviceId)
1474 .policyFlags(DEFAULT_POLICY_FLAGS)
1475 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1476 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1477 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001478 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1479 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1480 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1481 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1482
1483 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001484 mDispatcher->notifyMotion(
1485 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
1486 .deviceId(touchDeviceId)
1487 .policyFlags(0)
1488 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1489 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1490 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001491 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1492 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1493
1494 // We don't need to reset the device to reproduce the issue, but the reset event typically
1495 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001496 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001497
1498 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00001499 mDispatcher->notifyMotion(
1500 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1501 .deviceId(touchDeviceId)
1502 .policyFlags(DEFAULT_POLICY_FLAGS)
1503 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1504 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001505 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1506 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1507
1508 // No more events
1509 spyWindow->assertNoEvents();
1510 window->assertNoEvents();
1511}
1512
1513/**
Linnan Li907ae732023-09-05 17:14:21 +08001514 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
1515 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1516 * interactive, it might stop sending this flag.
1517 * We've already ensured the consistency of the touch event in this case, and we should also ensure
1518 * the consistency of the hover event in this case.
1519 *
1520 * Test procedure:
1521 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
1522 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
1523 *
1524 * We expect to receive two full streams of hover events.
1525 */
1526TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
1527 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1528
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001529 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1530 ui::LogicalDisplayId::DEFAULT);
Linnan Li907ae732023-09-05 17:14:21 +08001531 window->setFrame(Rect(0, 0, 300, 300));
1532
1533 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1534
1535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1536 .policyFlags(DEFAULT_POLICY_FLAGS)
1537 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
1538 .build());
1539 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1540
1541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1542 .policyFlags(DEFAULT_POLICY_FLAGS)
1543 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1544 .build());
1545 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1546
1547 // Send hover exit without the default policy flags.
1548 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1549 .policyFlags(0)
1550 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1551 .build());
1552
1553 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1554
1555 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
1556 // right event.
1557 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1558 .policyFlags(DEFAULT_POLICY_FLAGS)
1559 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
1560 .build());
1561 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1562
1563 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1564 .policyFlags(DEFAULT_POLICY_FLAGS)
1565 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1566 .build());
1567 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1568
1569 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1570 .policyFlags(DEFAULT_POLICY_FLAGS)
1571 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1572 .build());
1573 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1574}
1575
1576/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001577 * Two windows: a window on the left and a window on the right.
1578 * Mouse is hovered from the right window into the left window.
1579 * Next, we tap on the left window, where the cursor was last seen.
1580 * The second tap is done onto the right window.
1581 * The mouse and tap are from two different devices.
1582 * We technically don't need to set the downtime / eventtime for these events, but setting these
1583 * explicitly helps during debugging.
1584 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1585 * In the buggy implementation, a tap on the right window would cause a crash.
1586 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001587TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap_legacy) {
1588 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
1589
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001590 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001591 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1592 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001593 leftWindow->setFrame(Rect(0, 0, 200, 200));
1594
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001595 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1596 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001597 rightWindow->setFrame(Rect(200, 0, 400, 200));
1598
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001599 mDispatcher->onWindowInfosChanged(
1600 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001601 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1602 // stale.
1603 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1604 const int32_t mouseDeviceId = 6;
1605 const int32_t touchDeviceId = 4;
1606 // Move the cursor from right
1607 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001608 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001609 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1610 AINPUT_SOURCE_MOUSE)
1611 .deviceId(mouseDeviceId)
1612 .downTime(baseTime + 10)
1613 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001614 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001615 .build()));
1616 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1617
1618 // .. to the left window
1619 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001620 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001621 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1622 AINPUT_SOURCE_MOUSE)
1623 .deviceId(mouseDeviceId)
1624 .downTime(baseTime + 10)
1625 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001626 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001627 .build()));
1628 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1629 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1630 // Now tap the left window
1631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001632 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001633 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1634 AINPUT_SOURCE_TOUCHSCREEN)
1635 .deviceId(touchDeviceId)
1636 .downTime(baseTime + 40)
1637 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001638 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001639 .build()));
1640 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1641 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1642
1643 // release tap
1644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001645 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001646 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1647 AINPUT_SOURCE_TOUCHSCREEN)
1648 .deviceId(touchDeviceId)
1649 .downTime(baseTime + 40)
1650 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001651 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001652 .build()));
1653 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1654
1655 // Tap the window on the right
1656 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001657 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001658 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1659 AINPUT_SOURCE_TOUCHSCREEN)
1660 .deviceId(touchDeviceId)
1661 .downTime(baseTime + 60)
1662 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001663 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001664 .build()));
1665 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1666
1667 // release tap
1668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001669 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001670 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1671 AINPUT_SOURCE_TOUCHSCREEN)
1672 .deviceId(touchDeviceId)
1673 .downTime(baseTime + 60)
1674 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001675 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001676 .build()));
1677 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1678
1679 // No more events
1680 leftWindow->assertNoEvents();
1681 rightWindow->assertNoEvents();
1682}
1683
1684/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001685 * Two windows: a window on the left and a window on the right.
1686 * Mouse is hovered from the right window into the left window.
1687 * Next, we tap on the left window, where the cursor was last seen.
1688 * The second tap is done onto the right window.
1689 * The mouse and tap are from two different devices.
1690 * We technically don't need to set the downtime / eventtime for these events, but setting these
1691 * explicitly helps during debugging.
1692 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1693 * In the buggy implementation, a tap on the right window would cause a crash.
1694 */
1695TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
1696 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1697
1698 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001699 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1700 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001701 leftWindow->setFrame(Rect(0, 0, 200, 200));
1702
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001703 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1704 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001705 rightWindow->setFrame(Rect(200, 0, 400, 200));
1706
1707 mDispatcher->onWindowInfosChanged(
1708 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
1709 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1710 // stale.
1711 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1712 const int32_t mouseDeviceId = 6;
1713 const int32_t touchDeviceId = 4;
1714 // Move the cursor from right
1715 mDispatcher->notifyMotion(
1716 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1717 .deviceId(mouseDeviceId)
1718 .downTime(baseTime + 10)
1719 .eventTime(baseTime + 20)
1720 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
1721 .build());
1722 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1723
1724 // .. to the left window
1725 mDispatcher->notifyMotion(
1726 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1727 .deviceId(mouseDeviceId)
1728 .downTime(baseTime + 10)
1729 .eventTime(baseTime + 30)
1730 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
1731 .build());
1732 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1733 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1734 // Now tap the left window
1735 mDispatcher->notifyMotion(
1736 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1737 .deviceId(touchDeviceId)
1738 .downTime(baseTime + 40)
1739 .eventTime(baseTime + 40)
1740 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1741 .build());
1742 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1743
1744 // release tap
1745 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1746 .deviceId(touchDeviceId)
1747 .downTime(baseTime + 40)
1748 .eventTime(baseTime + 50)
1749 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1750 .build());
1751 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1752
1753 // Tap the window on the right
1754 mDispatcher->notifyMotion(
1755 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1756 .deviceId(touchDeviceId)
1757 .downTime(baseTime + 60)
1758 .eventTime(baseTime + 60)
1759 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1760 .build());
1761 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1762
1763 // release tap
1764 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1765 .deviceId(touchDeviceId)
1766 .downTime(baseTime + 60)
1767 .eventTime(baseTime + 70)
1768 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1769 .build());
1770 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1771
1772 // No more events
1773 leftWindow->assertNoEvents();
1774 rightWindow->assertNoEvents();
1775}
1776
1777/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001778 * Start hovering in a window. While this hover is still active, make another window appear on top.
1779 * The top, obstructing window has no input channel, so it's not supposed to receive input.
1780 * While the top window is present, the hovering is stopped.
1781 * Later, hovering gets resumed again.
1782 * Ensure that new hover gesture is handled correctly.
1783 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
1784 * to the window that's currently being hovered over.
1785 */
1786TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
1787 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001788 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1789 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001790 window->setFrame(Rect(0, 0, 200, 200));
1791
1792 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001793 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001794
1795 // Start hovering in the window
1796 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1797 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1798 .build());
1799 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1800
1801 // Now, an obscuring window appears!
1802 sp<FakeWindowHandle> obscuringWindow =
1803 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001804 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001805 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001806 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1807 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1808 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1809 obscuringWindow->setNoInputChannel(true);
1810 obscuringWindow->setFocusable(false);
1811 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001812 mDispatcher->onWindowInfosChanged(
1813 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001814
1815 // While this new obscuring window is present, the hovering is stopped
1816 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1817 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1818 .build());
1819 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1820
1821 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001822 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001823
1824 // And a new hover gesture starts.
1825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1826 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1827 .build());
1828 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1829}
1830
1831/**
1832 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
1833 * the obscuring window.
1834 */
1835TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
1836 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001837 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1838 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001839 window->setFrame(Rect(0, 0, 200, 200));
1840
1841 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001842 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001843
1844 // Start hovering in the window
1845 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1846 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1847 .build());
1848 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1849
1850 // Now, an obscuring window appears!
1851 sp<FakeWindowHandle> obscuringWindow =
1852 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001853 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001854 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001855 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1856 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1857 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1858 obscuringWindow->setNoInputChannel(true);
1859 obscuringWindow->setFocusable(false);
1860 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001861 mDispatcher->onWindowInfosChanged(
1862 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001863
1864 // While this new obscuring window is present, the hovering continues. The event can't go to the
1865 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
1866 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1867 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1868 .build());
1869 obscuringWindow->assertNoEvents();
1870 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1871
1872 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001873 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001874
1875 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
1876 // so it should generate a HOVER_ENTER
1877 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1878 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1879 .build());
1880 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1881
1882 // Now the MOVE should be getting dispatched normally
1883 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1884 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
1885 .build());
1886 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1887}
1888
1889/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001890 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
1891 * events are delivered to the window.
1892 */
1893TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
1894 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001895 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1896 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001897 window->setFrame(Rect(0, 0, 200, 200));
1898 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1899
1900 // Start hovering in the window
1901 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
1902 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1903 .build());
1904 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1905
1906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1907 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1908 .build());
1909 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1910
1911 // Scroll with the mouse
1912 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
1913 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1914 .build());
1915 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
1916}
1917
1918using InputDispatcherMultiDeviceTest = InputDispatcherTest;
1919
1920/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001921 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
1922 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001923 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001924TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001925 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001926 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001927 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1928 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001929 window->setFrame(Rect(0, 0, 200, 200));
1930
1931 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1932
1933 constexpr int32_t touchDeviceId = 4;
1934 constexpr int32_t stylusDeviceId = 2;
1935
1936 // Stylus down
1937 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1938 .deviceId(stylusDeviceId)
1939 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
1940 .build());
1941 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
1942
1943 // Touch down
1944 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1945 .deviceId(touchDeviceId)
1946 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
1947 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001948
1949 // Touch move
1950 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1951 .deviceId(touchDeviceId)
1952 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
1953 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001954 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001955
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001956 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001957 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
1958 .deviceId(stylusDeviceId)
1959 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
1960 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001961 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
1962 WithCoords(101, 111)));
1963
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001964 window->assertNoEvents();
1965}
1966
1967/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001968 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
1969 * touch is not dropped, because multiple devices are allowed to be active in the same window.
1970 */
1971TEST_F(InputDispatcherMultiDeviceTest, StylusDownDoesNotBlockTouchDown) {
1972 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1973 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001974 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1975 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001976 window->setFrame(Rect(0, 0, 200, 200));
1977
1978 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1979
1980 constexpr int32_t touchDeviceId = 4;
1981 constexpr int32_t stylusDeviceId = 2;
1982
1983 // Stylus down
1984 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1985 .deviceId(stylusDeviceId)
1986 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
1987 .build());
1988 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
1989
1990 // Touch down
1991 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1992 .deviceId(touchDeviceId)
1993 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
1994 .build());
1995 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
1996
1997 // Touch move
1998 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1999 .deviceId(touchDeviceId)
2000 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2001 .build());
2002 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2003
2004 // Stylus move
2005 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2006 .deviceId(stylusDeviceId)
2007 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2008 .build());
2009 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2010 WithCoords(101, 111)));
2011
2012 window->assertNoEvents();
2013}
2014
2015/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002016 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002017 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002018 * Similar test as above, but with added SPY window.
2019 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002020TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002021 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002022 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002023 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2024 ui::LogicalDisplayId::DEFAULT);
2025 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2026 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002027 spyWindow->setFrame(Rect(0, 0, 200, 200));
2028 spyWindow->setTrustedOverlay(true);
2029 spyWindow->setSpy(true);
2030 window->setFrame(Rect(0, 0, 200, 200));
2031
2032 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2033
2034 constexpr int32_t touchDeviceId = 4;
2035 constexpr int32_t stylusDeviceId = 2;
2036
2037 // Stylus down
2038 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2039 .deviceId(stylusDeviceId)
2040 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2041 .build());
2042 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2043 spyWindow->consumeMotionEvent(
2044 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2045
2046 // Touch down
2047 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2048 .deviceId(touchDeviceId)
2049 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2050 .build());
2051
2052 // Touch move
2053 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2054 .deviceId(touchDeviceId)
2055 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2056 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002057
2058 // Touch is ignored because stylus is already down
2059
2060 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002061 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2062 .deviceId(stylusDeviceId)
2063 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2064 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002065 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2066 WithCoords(101, 111)));
2067 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2068 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002069
2070 window->assertNoEvents();
2071 spyWindow->assertNoEvents();
2072}
2073
2074/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002075 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2076 * down. Ensure that touch is not dropped, because multiple devices can be active at the same time.
2077 * Similar test as above, but with added SPY window.
2078 */
2079TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyDoesNotBlockTouchDown) {
2080 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2081 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002082 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2083 ui::LogicalDisplayId::DEFAULT);
2084 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2085 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002086 spyWindow->setFrame(Rect(0, 0, 200, 200));
2087 spyWindow->setTrustedOverlay(true);
2088 spyWindow->setSpy(true);
2089 window->setFrame(Rect(0, 0, 200, 200));
2090
2091 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2092
2093 constexpr int32_t touchDeviceId = 4;
2094 constexpr int32_t stylusDeviceId = 2;
2095
2096 // Stylus down
2097 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2098 .deviceId(stylusDeviceId)
2099 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2100 .build());
2101 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2102 spyWindow->consumeMotionEvent(
2103 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2104
2105 // Touch down
2106 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2107 .deviceId(touchDeviceId)
2108 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2109 .build());
2110 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2111 spyWindow->consumeMotionEvent(
2112 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2113
2114 // Touch move
2115 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2116 .deviceId(touchDeviceId)
2117 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2118 .build());
2119 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2120 spyWindow->consumeMotionEvent(
2121 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2122
2123 // Subsequent stylus movements are delivered correctly
2124 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2125 .deviceId(stylusDeviceId)
2126 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2127 .build());
2128 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2129 WithCoords(101, 111)));
2130 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2131 WithCoords(101, 111)));
2132
2133 window->assertNoEvents();
2134 spyWindow->assertNoEvents();
2135}
2136
2137/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002138 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002139 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002140 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002141TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002142 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002143 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002144 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2145 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002146 window->setFrame(Rect(0, 0, 200, 200));
2147
2148 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2149
2150 constexpr int32_t touchDeviceId = 4;
2151 constexpr int32_t stylusDeviceId = 2;
2152
2153 // Stylus down on the window
2154 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2155 .deviceId(stylusDeviceId)
2156 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2157 .build());
2158 window->consumeMotionEvent(
2159 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2160
2161 // Touch down on window
2162 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2163 .deviceId(touchDeviceId)
2164 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2165 .build());
2166 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2167 .deviceId(touchDeviceId)
2168 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2169 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002170
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002171 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002172
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002173 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002174 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2175 .deviceId(stylusDeviceId)
2176 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2177 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002178 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2179 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002180
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002181 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002182 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2183 .deviceId(touchDeviceId)
2184 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2185 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002186 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002187}
2188
2189/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002190 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2191 * touch is not dropped, because stylus hover and touch can be both active at the same time.
2192 */
2193TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
2194 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2195 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002196 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2197 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002198 window->setFrame(Rect(0, 0, 200, 200));
2199
2200 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2201
2202 constexpr int32_t touchDeviceId = 4;
2203 constexpr int32_t stylusDeviceId = 2;
2204
2205 // Stylus down on the window
2206 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2207 .deviceId(stylusDeviceId)
2208 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2209 .build());
2210 window->consumeMotionEvent(
2211 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2212
2213 // Touch down on window
2214 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2215 .deviceId(touchDeviceId)
2216 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2217 .build());
2218 // Touch move on window
2219 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2220 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2221 .deviceId(touchDeviceId)
2222 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2223 .build());
2224 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2225
2226 // Subsequent stylus movements are delivered correctly
2227 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2228 .deviceId(stylusDeviceId)
2229 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2230 .build());
2231 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2232 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2233
2234 // and subsequent touches continue to work
2235 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2236 .deviceId(touchDeviceId)
2237 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2238 .build());
2239 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2240 window->assertNoEvents();
2241}
2242
2243/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002244 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002245 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002246 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002247TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002248 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002249 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002250 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2251 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002252 window->setFrame(Rect(0, 0, 200, 200));
2253
2254 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2255
2256 constexpr int32_t touchDeviceId = 4;
2257 constexpr int32_t stylusDeviceId = 2;
2258
2259 // Touch down on window
2260 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2261 .deviceId(touchDeviceId)
2262 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2263 .build());
2264 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2265 .deviceId(touchDeviceId)
2266 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2267 .build());
2268 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2269 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2270
2271 // Stylus hover on the window
2272 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2273 .deviceId(stylusDeviceId)
2274 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2275 .build());
2276 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2277 .deviceId(stylusDeviceId)
2278 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2279 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002280 // Stylus hover movement causes touch to be canceled
2281 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2282 WithCoords(141, 146)));
2283 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2284 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2285 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2286 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002287
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002288 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002289 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2290 .deviceId(touchDeviceId)
2291 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2292 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002293
2294 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002295}
2296
2297/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002298 * One window. Touch down on the window. Then, stylus hover on the window from another device.
2299 * Ensure that touch is not canceled, because stylus hover can be active at the same time as touch.
2300 */
2301TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2302 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2303 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002304 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2305 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002306 window->setFrame(Rect(0, 0, 200, 200));
2307
2308 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2309
2310 constexpr int32_t touchDeviceId = 4;
2311 constexpr int32_t stylusDeviceId = 2;
2312
2313 // Touch down on window
2314 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2315 .deviceId(touchDeviceId)
2316 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2317 .build());
2318 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2319 .deviceId(touchDeviceId)
2320 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2321 .build());
2322 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2323 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2324
2325 // Stylus hover on the window
2326 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2327 .deviceId(stylusDeviceId)
2328 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2329 .build());
2330 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2331 .deviceId(stylusDeviceId)
2332 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2333 .build());
2334 // Stylus hover movement is received normally
2335 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2336 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2337 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2338 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2339
2340 // Subsequent touch movements also work
2341 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2342 .deviceId(touchDeviceId)
2343 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2344 .build());
2345 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2346 WithCoords(142, 147)));
2347
2348 window->assertNoEvents();
2349}
2350
2351/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002352 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2353 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2354 * become active.
2355 */
2356TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002357 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002359 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2360 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002361 window->setFrame(Rect(0, 0, 200, 200));
2362
2363 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2364
2365 constexpr int32_t stylusDeviceId1 = 3;
2366 constexpr int32_t stylusDeviceId2 = 5;
2367
2368 // Touch down on window
2369 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2370 .deviceId(stylusDeviceId1)
2371 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2372 .build());
2373 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2374 .deviceId(stylusDeviceId1)
2375 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2376 .build());
2377 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2378 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2379
2380 // Second stylus down
2381 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2382 .deviceId(stylusDeviceId2)
2383 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2384 .build());
2385 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2386 .deviceId(stylusDeviceId2)
2387 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2388 .build());
2389
2390 // First stylus is canceled, second one takes over.
2391 window->consumeMotionEvent(
2392 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2393 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2394 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2395
2396 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2397 .deviceId(stylusDeviceId1)
2398 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2399 .build());
2400 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002401 window->assertNoEvents();
2402}
2403
2404/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002405 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2406 * both stylus devices can function simultaneously.
2407 */
2408TEST_F(InputDispatcherMultiDeviceTest, TwoStylusDevicesActiveAtTheSameTime) {
2409 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2410 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002411 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2412 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002413 window->setFrame(Rect(0, 0, 200, 200));
2414
2415 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2416
2417 constexpr int32_t stylusDeviceId1 = 3;
2418 constexpr int32_t stylusDeviceId2 = 5;
2419
2420 // Touch down on window
2421 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2422 .deviceId(stylusDeviceId1)
2423 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2424 .build());
2425 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2426 .deviceId(stylusDeviceId1)
2427 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2428 .build());
2429 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2430 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2431
2432 // Second stylus down
2433 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2434 .deviceId(stylusDeviceId2)
2435 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2436 .build());
2437 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2438 .deviceId(stylusDeviceId2)
2439 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2440 .build());
2441 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2442 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2443
2444 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2445 .deviceId(stylusDeviceId1)
2446 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2447 .build());
2448 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2449 window->assertNoEvents();
2450}
2451
2452/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002453 * One window. Touch down on the window. Then, stylus down on the window from another device.
2454 * Ensure that is canceled, because stylus down should be preferred over touch.
2455 */
2456TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002457 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002458 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002459 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2460 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002461 window->setFrame(Rect(0, 0, 200, 200));
2462
2463 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2464
2465 constexpr int32_t touchDeviceId = 4;
2466 constexpr int32_t stylusDeviceId = 2;
2467
2468 // Touch down on window
2469 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2470 .deviceId(touchDeviceId)
2471 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2472 .build());
2473 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2474 .deviceId(touchDeviceId)
2475 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2476 .build());
2477 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2478 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2479
2480 // Stylus down on the window
2481 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2482 .deviceId(stylusDeviceId)
2483 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2484 .build());
2485 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2486 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2487
2488 // Subsequent stylus movements are delivered correctly
2489 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2490 .deviceId(stylusDeviceId)
2491 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2492 .build());
2493 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2494 WithCoords(101, 111)));
2495}
2496
2497/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002498 * One window. Touch down on the window. Then, stylus down on the window from another device.
2499 * Ensure that both touch and stylus are functioning independently.
2500 */
2501TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusDown) {
2502 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2503 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002504 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2505 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002506 window->setFrame(Rect(0, 0, 200, 200));
2507
2508 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2509
2510 constexpr int32_t touchDeviceId = 4;
2511 constexpr int32_t stylusDeviceId = 2;
2512
2513 // Touch down on window
2514 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2515 .deviceId(touchDeviceId)
2516 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2517 .build());
2518 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2519 .deviceId(touchDeviceId)
2520 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2521 .build());
2522 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2523 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2524
2525 // Stylus down on the window
2526 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2527 .deviceId(stylusDeviceId)
2528 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2529 .build());
2530 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2531
2532 // Subsequent stylus movements are delivered correctly
2533 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2534 .deviceId(stylusDeviceId)
2535 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2536 .build());
2537 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2538 WithCoords(101, 111)));
2539
2540 // Touch continues to work too
2541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2542 .deviceId(touchDeviceId)
2543 .pointer(PointerBuilder(0, ToolType::FINGER).x(148).y(149))
2544 .build());
2545 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2546}
2547
2548/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002549 * Two windows: a window on the left and a window on the right.
2550 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2551 * down. Then, on the left window, also place second touch pointer down.
2552 * This test tries to reproduce a crash.
2553 * In the buggy implementation, second pointer down on the left window would cause a crash.
2554 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002555TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch_legacy) {
2556 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002557 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002558 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2559 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002560 leftWindow->setFrame(Rect(0, 0, 200, 200));
2561
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002562 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2563 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002564 rightWindow->setFrame(Rect(200, 0, 400, 200));
2565
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002566 mDispatcher->onWindowInfosChanged(
2567 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002568
2569 const int32_t touchDeviceId = 4;
2570 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002571
2572 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002573 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2574 .deviceId(mouseDeviceId)
2575 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2576 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002577 leftWindow->consumeMotionEvent(
2578 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2579
2580 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002581 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2582 .deviceId(mouseDeviceId)
2583 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2584 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2585 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002586
2587 leftWindow->consumeMotionEvent(
2588 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2589 leftWindow->consumeMotionEvent(
2590 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2591
Prabir Pradhan678438e2023-04-13 19:32:51 +00002592 mDispatcher->notifyMotion(
2593 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2594 .deviceId(mouseDeviceId)
2595 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2596 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2597 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2598 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002599 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2600
2601 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002602 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2603 .deviceId(touchDeviceId)
2604 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2605 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002606 leftWindow->assertNoEvents();
2607
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002608 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2609
2610 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002611 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2612 .deviceId(touchDeviceId)
2613 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2614 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2615 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002616 // Since this is now a new splittable pointer going down on the left window, and it's coming
2617 // from a different device, the current gesture in the left window (pointer down) should first
2618 // be canceled.
2619 leftWindow->consumeMotionEvent(
2620 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002621 leftWindow->consumeMotionEvent(
2622 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2623 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2624 // current implementation.
2625 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2626 rightWindow->consumeMotionEvent(
2627 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2628
2629 leftWindow->assertNoEvents();
2630 rightWindow->assertNoEvents();
2631}
2632
2633/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002634 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002635 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2636 * down. Then, on the left window, also place second touch pointer down.
2637 * This test tries to reproduce a crash.
2638 * In the buggy implementation, second pointer down on the left window would cause a crash.
2639 */
2640TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
2641 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2642 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002643 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2644 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002645 leftWindow->setFrame(Rect(0, 0, 200, 200));
2646
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002647 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2648 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002649 rightWindow->setFrame(Rect(200, 0, 400, 200));
2650
2651 mDispatcher->onWindowInfosChanged(
2652 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2653
2654 const int32_t touchDeviceId = 4;
2655 const int32_t mouseDeviceId = 6;
2656
2657 // Start hovering over the left window
2658 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2659 .deviceId(mouseDeviceId)
2660 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2661 .build());
2662 leftWindow->consumeMotionEvent(
2663 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2664
2665 // Mouse down on left window
2666 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2667 .deviceId(mouseDeviceId)
2668 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2669 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2670 .build());
2671
2672 leftWindow->consumeMotionEvent(
2673 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2674 leftWindow->consumeMotionEvent(
2675 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2676
2677 mDispatcher->notifyMotion(
2678 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2679 .deviceId(mouseDeviceId)
2680 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2681 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2682 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2683 .build());
2684 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2685
2686 // First touch pointer down on right window
2687 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2688 .deviceId(touchDeviceId)
2689 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2690 .build());
2691 leftWindow->assertNoEvents();
2692
2693 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2694
2695 // Second touch pointer down on left window
2696 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2697 .deviceId(touchDeviceId)
2698 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2699 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2700 .build());
2701 // Since this is now a new splittable pointer going down on the left window, and it's coming
2702 // from a different device, it will be split and delivered to left window separately.
2703 leftWindow->consumeMotionEvent(
2704 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2705 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2706 // current implementation.
2707 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2708 rightWindow->consumeMotionEvent(
2709 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2710
2711 leftWindow->assertNoEvents();
2712 rightWindow->assertNoEvents();
2713}
2714
2715/**
2716 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002717 * Mouse is hovered on the left window and stylus is hovered on the right window.
2718 */
2719TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2720 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002721 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2722 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002723 leftWindow->setFrame(Rect(0, 0, 200, 200));
2724
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002725 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2726 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002727 rightWindow->setFrame(Rect(200, 0, 400, 200));
2728
2729 mDispatcher->onWindowInfosChanged(
2730 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2731
2732 const int32_t stylusDeviceId = 3;
2733 const int32_t mouseDeviceId = 6;
2734
2735 // Start hovering over the left window
2736 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2737 .deviceId(mouseDeviceId)
2738 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2739 .build());
2740 leftWindow->consumeMotionEvent(
2741 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2742
2743 // Stylus hovered on right window
2744 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2745 .deviceId(stylusDeviceId)
2746 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2747 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002748 rightWindow->consumeMotionEvent(
2749 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2750
2751 // Subsequent HOVER_MOVE events are dispatched correctly.
2752 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2753 .deviceId(mouseDeviceId)
2754 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2755 .build());
2756 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002757 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002758
2759 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2760 .deviceId(stylusDeviceId)
2761 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2762 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002763 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002764 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002765
2766 leftWindow->assertNoEvents();
2767 rightWindow->assertNoEvents();
2768}
2769
2770/**
2771 * Three windows: a window on the left and a window on the right.
2772 * And a spy window that's positioned above all of them.
2773 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2774 * Check the stream that's received by the spy.
2775 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002776TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy_legacy) {
2777 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002778 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2779
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002780 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2781 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002782 spyWindow->setFrame(Rect(0, 0, 400, 400));
2783 spyWindow->setTrustedOverlay(true);
2784 spyWindow->setSpy(true);
2785
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002786 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2787 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002788 leftWindow->setFrame(Rect(0, 0, 200, 200));
2789
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002790 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2791 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002792
2793 rightWindow->setFrame(Rect(200, 0, 400, 200));
2794
2795 mDispatcher->onWindowInfosChanged(
2796 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2797
2798 const int32_t stylusDeviceId = 1;
2799 const int32_t touchDeviceId = 2;
2800
2801 // Stylus down on the left window
2802 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2803 .deviceId(stylusDeviceId)
2804 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2805 .build());
2806 leftWindow->consumeMotionEvent(
2807 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2808 spyWindow->consumeMotionEvent(
2809 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2810
2811 // Touch down on the right window
2812 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2813 .deviceId(touchDeviceId)
2814 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2815 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002816 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002817 rightWindow->consumeMotionEvent(
2818 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002819
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002820 // Spy window does not receive touch events, because stylus events take precedence, and it
2821 // already has an active stylus gesture.
2822
2823 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2825 .deviceId(stylusDeviceId)
2826 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2827 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002828 leftWindow->consumeMotionEvent(
2829 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2830 spyWindow->consumeMotionEvent(
2831 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002832
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002833 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002834 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2835 .deviceId(touchDeviceId)
2836 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2837 .build());
2838 rightWindow->consumeMotionEvent(
2839 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002840
2841 spyWindow->assertNoEvents();
2842 leftWindow->assertNoEvents();
2843 rightWindow->assertNoEvents();
2844}
2845
2846/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002847 * Three windows: a window on the left and a window on the right.
2848 * And a spy window that's positioned above all of them.
2849 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2850 * Check the stream that's received by the spy.
2851 */
2852TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2853 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2854 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2855
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002856 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2857 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002858 spyWindow->setFrame(Rect(0, 0, 400, 400));
2859 spyWindow->setTrustedOverlay(true);
2860 spyWindow->setSpy(true);
2861
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002862 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2863 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002864 leftWindow->setFrame(Rect(0, 0, 200, 200));
2865
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002866 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2867 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002868
2869 rightWindow->setFrame(Rect(200, 0, 400, 200));
2870
2871 mDispatcher->onWindowInfosChanged(
2872 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2873
2874 const int32_t stylusDeviceId = 1;
2875 const int32_t touchDeviceId = 2;
2876
2877 // Stylus down on the left window
2878 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2879 .deviceId(stylusDeviceId)
2880 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2881 .build());
2882 leftWindow->consumeMotionEvent(
2883 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2884 spyWindow->consumeMotionEvent(
2885 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2886
2887 // Touch down on the right window
2888 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2889 .deviceId(touchDeviceId)
2890 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2891 .build());
2892 leftWindow->assertNoEvents();
2893 rightWindow->consumeMotionEvent(
2894 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2895 spyWindow->consumeMotionEvent(
2896 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2897
2898 // Stylus movements continue. They should be delivered to the left window and to the spy window
2899 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2900 .deviceId(stylusDeviceId)
2901 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2902 .build());
2903 leftWindow->consumeMotionEvent(
2904 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2905 spyWindow->consumeMotionEvent(
2906 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2907
2908 // Further touch MOVE events keep going to the right window and to the spy
2909 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2910 .deviceId(touchDeviceId)
2911 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2912 .build());
2913 rightWindow->consumeMotionEvent(
2914 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2915 spyWindow->consumeMotionEvent(
2916 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2917
2918 spyWindow->assertNoEvents();
2919 leftWindow->assertNoEvents();
2920 rightWindow->assertNoEvents();
2921}
2922
2923/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002924 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2925 * both.
2926 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002927 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002928 * At the same time, left and right should be getting independent streams of hovering and touch,
2929 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002930 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002931TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002932 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002933 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2934
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002935 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2936 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002937 spyWindow->setFrame(Rect(0, 0, 400, 400));
2938 spyWindow->setTrustedOverlay(true);
2939 spyWindow->setSpy(true);
2940
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002941 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2942 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002943 leftWindow->setFrame(Rect(0, 0, 200, 200));
2944
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002945 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2946 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002947 rightWindow->setFrame(Rect(200, 0, 400, 200));
2948
2949 mDispatcher->onWindowInfosChanged(
2950 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2951
2952 const int32_t stylusDeviceId = 1;
2953 const int32_t touchDeviceId = 2;
2954
2955 // Stylus hover on the left window
2956 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2957 .deviceId(stylusDeviceId)
2958 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2959 .build());
2960 leftWindow->consumeMotionEvent(
2961 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2962 spyWindow->consumeMotionEvent(
2963 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2964
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002965 // Touch down on the right window. Spy doesn't receive this touch because it already has
2966 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002967 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2968 .deviceId(touchDeviceId)
2969 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2970 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002971 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002972 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002973 rightWindow->consumeMotionEvent(
2974 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2975
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002976 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002977 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2978 .deviceId(stylusDeviceId)
2979 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2980 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002981 leftWindow->consumeMotionEvent(
2982 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002983 spyWindow->consumeMotionEvent(
2984 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002985
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002986 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002987 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2988 .deviceId(touchDeviceId)
2989 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2990 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002991 rightWindow->consumeMotionEvent(
2992 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2993
2994 spyWindow->assertNoEvents();
2995 leftWindow->assertNoEvents();
2996 rightWindow->assertNoEvents();
2997}
2998
2999/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003000 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3001 * both.
3002 * Check hover in left window and touch down in the right window.
3003 * At first, spy should receive hover. Next, spy should receive touch.
3004 * At the same time, left and right should be getting independent streams of hovering and touch,
3005 * respectively.
3006 */
3007TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverDoesNotBlockTouchWithSpy) {
3008 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3009 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3010
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003011 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3012 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003013 spyWindow->setFrame(Rect(0, 0, 400, 400));
3014 spyWindow->setTrustedOverlay(true);
3015 spyWindow->setSpy(true);
3016
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003017 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3018 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003019 leftWindow->setFrame(Rect(0, 0, 200, 200));
3020
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003021 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3022 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003023 rightWindow->setFrame(Rect(200, 0, 400, 200));
3024
3025 mDispatcher->onWindowInfosChanged(
3026 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3027
3028 const int32_t stylusDeviceId = 1;
3029 const int32_t touchDeviceId = 2;
3030
3031 // Stylus hover on the left window
3032 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3033 .deviceId(stylusDeviceId)
3034 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3035 .build());
3036 leftWindow->consumeMotionEvent(
3037 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3038 spyWindow->consumeMotionEvent(
3039 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3040
3041 // Touch down on the right window.
3042 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3043 .deviceId(touchDeviceId)
3044 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3045 .build());
3046 leftWindow->assertNoEvents();
3047 spyWindow->consumeMotionEvent(
3048 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3049 rightWindow->consumeMotionEvent(
3050 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3051
3052 // Stylus movements continue. They should be delivered to the left window and the spy.
3053 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3054 .deviceId(stylusDeviceId)
3055 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3056 .build());
3057 leftWindow->consumeMotionEvent(
3058 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3059 spyWindow->consumeMotionEvent(
3060 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3061
3062 // Touch movements continue. They should be delivered to the right window and the spy
3063 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3064 .deviceId(touchDeviceId)
3065 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3066 .build());
3067 rightWindow->consumeMotionEvent(
3068 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3069 spyWindow->consumeMotionEvent(
3070 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3071
3072 spyWindow->assertNoEvents();
3073 leftWindow->assertNoEvents();
3074 rightWindow->assertNoEvents();
3075}
3076
3077/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003078 * On a single window, use two different devices: mouse and touch.
3079 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3080 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3081 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3082 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3083 * represent a new gesture.
3084 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003085TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown_legacy) {
3086 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003087 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003088 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3089 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003090 window->setFrame(Rect(0, 0, 400, 400));
3091
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003092 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003093
3094 const int32_t touchDeviceId = 4;
3095 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003096
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003097 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003098 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3099 .deviceId(touchDeviceId)
3100 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3101 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003102 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003103 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3104 .deviceId(touchDeviceId)
3105 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3106 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3107 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003108 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003109 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3110 .deviceId(touchDeviceId)
3111 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3112 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3113 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003114 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3115 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3116 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3117
3118 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003119 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3120 .deviceId(mouseDeviceId)
3121 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3122 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3123 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003124
3125 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003126 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003127 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3128
Prabir Pradhan678438e2023-04-13 19:32:51 +00003129 mDispatcher->notifyMotion(
3130 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3131 .deviceId(mouseDeviceId)
3132 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3133 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3134 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3135 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003136 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3137
3138 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003139 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3140 .deviceId(touchDeviceId)
3141 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3142 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3143 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003144 // Since we already canceled this touch gesture, it will be ignored until a completely new
3145 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3146 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3147 // However, mouse movements should continue to work.
3148 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3149 .deviceId(mouseDeviceId)
3150 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3151 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3152 .build());
3153 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3154
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003155 window->assertNoEvents();
3156}
3157
3158/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003159 * On a single window, use two different devices: mouse and touch.
3160 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3161 * Mouse is clicked next, which should not interfere with the touch stream.
3162 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is also
3163 * delivered correctly.
3164 */
3165TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
3166 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3167 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003168 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3169 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003170 window->setFrame(Rect(0, 0, 400, 400));
3171
3172 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3173
3174 const int32_t touchDeviceId = 4;
3175 const int32_t mouseDeviceId = 6;
3176
3177 // First touch pointer down
3178 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3179 .deviceId(touchDeviceId)
3180 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3181 .build());
3182 // Second touch pointer down
3183 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3184 .deviceId(touchDeviceId)
3185 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3186 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3187 .build());
3188 // First touch pointer lifts. The second one remains down
3189 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3190 .deviceId(touchDeviceId)
3191 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3192 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3193 .build());
3194 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3195 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3196 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3197
3198 // Mouse down
3199 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3200 .deviceId(mouseDeviceId)
3201 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3202 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3203 .build());
3204
3205 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3206
3207 mDispatcher->notifyMotion(
3208 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3209 .deviceId(mouseDeviceId)
3210 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3211 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3212 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3213 .build());
3214 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3215
3216 // Second touch pointer down.
3217 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, 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(AllOf(WithMotionAction(POINTER_0_DOWN), WithDeviceId(touchDeviceId),
3223 WithPointerCount(2u)));
3224
3225 // Mouse movements should continue to work
3226 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3227 .deviceId(mouseDeviceId)
3228 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3229 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3230 .build());
3231 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3232
3233 window->assertNoEvents();
3234}
3235
3236/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003237 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3238 * the injected event.
3239 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003240TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent_legacy) {
3241 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003242 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003243 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3244 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003245 window->setFrame(Rect(0, 0, 400, 400));
3246
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003247 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003248
3249 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003250 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3251 // completion.
3252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003253 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003254 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3255 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003256 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003257 .build()));
3258 window->consumeMotionEvent(
3259 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3260
3261 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3262 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003263 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3264 .deviceId(touchDeviceId)
3265 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3266 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003267
3268 window->consumeMotionEvent(
3269 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3270 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3271}
3272
3273/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003274 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event runs
3275 * parallel to the injected event.
3276 */
3277TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
3278 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3279 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003280 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3281 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003282 window->setFrame(Rect(0, 0, 400, 400));
3283
3284 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3285
3286 const int32_t touchDeviceId = 4;
3287 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3288 // completion.
3289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3290 injectMotionEvent(*mDispatcher,
3291 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3292 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
3293 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3294 .build()));
3295 window->consumeMotionEvent(
3296 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3297
3298 // Now a real touch comes. The injected pointer will remain, and the new gesture will also be
3299 // allowed through.
3300 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3301 .deviceId(touchDeviceId)
3302 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3303 .build());
3304 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3305}
3306
3307/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003308 * This test is similar to the test above, but the sequence of injected events is different.
3309 *
3310 * Two windows: a window on the left and a window on the right.
3311 * Mouse is hovered over the left window.
3312 * Next, we tap on the left window, where the cursor was last seen.
3313 *
3314 * After that, we inject one finger down onto the right window, and then a second finger down onto
3315 * the left window.
3316 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3317 * window (first), and then another on the left window (second).
3318 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3319 * In the buggy implementation, second finger down on the left window would cause a crash.
3320 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003321TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch_legacy) {
3322 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003323 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003324 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3325 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003326 leftWindow->setFrame(Rect(0, 0, 200, 200));
3327
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003328 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3329 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003330 rightWindow->setFrame(Rect(200, 0, 400, 200));
3331
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003332 mDispatcher->onWindowInfosChanged(
3333 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003334
3335 const int32_t mouseDeviceId = 6;
3336 const int32_t touchDeviceId = 4;
3337 // Hover over the left window. Keep the cursor there.
3338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003339 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003340 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3341 AINPUT_SOURCE_MOUSE)
3342 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003343 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003344 .build()));
3345 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3346
3347 // Tap on left window
3348 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003349 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003350 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3351 AINPUT_SOURCE_TOUCHSCREEN)
3352 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003353 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003354 .build()));
3355
3356 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003357 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003358 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3359 AINPUT_SOURCE_TOUCHSCREEN)
3360 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003361 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003362 .build()));
3363 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3364 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3365 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3366
3367 // First finger down on right window
3368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003369 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003370 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3371 AINPUT_SOURCE_TOUCHSCREEN)
3372 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003373 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003374 .build()));
3375 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3376
3377 // Second finger down on the left window
3378 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003379 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003380 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3381 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003382 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3383 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003384 .build()));
3385 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3386 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3387
3388 // No more events
3389 leftWindow->assertNoEvents();
3390 rightWindow->assertNoEvents();
3391}
3392
3393/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003394 * This test is similar to the test above, but the sequence of injected events is different.
3395 *
3396 * Two windows: a window on the left and a window on the right.
3397 * Mouse is hovered over the left window.
3398 * Next, we tap on the left window, where the cursor was last seen.
3399 *
3400 * After that, we send one finger down onto the right window, and then a second finger down onto
3401 * the left window.
3402 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3403 * window (first), and then another on the left window (second).
3404 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3405 * In the buggy implementation, second finger down on the left window would cause a crash.
3406 */
3407TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
3408 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3409 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003410 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3411 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003412 leftWindow->setFrame(Rect(0, 0, 200, 200));
3413
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003414 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3415 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003416 rightWindow->setFrame(Rect(200, 0, 400, 200));
3417
3418 mDispatcher->onWindowInfosChanged(
3419 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3420
3421 const int32_t mouseDeviceId = 6;
3422 const int32_t touchDeviceId = 4;
3423 // Hover over the left window. Keep the cursor there.
3424 mDispatcher->notifyMotion(
3425 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3426 .deviceId(mouseDeviceId)
3427 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3428 .build());
3429 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3430
3431 // Tap on left window
3432 mDispatcher->notifyMotion(
3433 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3434 .deviceId(touchDeviceId)
3435 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3436 .build());
3437
3438 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3439 .deviceId(touchDeviceId)
3440 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3441 .build());
3442 leftWindow->consumeMotionEvent(
3443 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithDeviceId(touchDeviceId)));
3444 leftWindow->consumeMotionEvent(
3445 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithDeviceId(touchDeviceId)));
3446
3447 // First finger down on right window
3448 mDispatcher->notifyMotion(
3449 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3450 .deviceId(touchDeviceId)
3451 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3452 .build());
3453 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3454
3455 // Second finger down on the left window
3456 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3457 .deviceId(touchDeviceId)
3458 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3459 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
3460 .build());
3461 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3462 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3463
3464 // No more events
3465 leftWindow->assertNoEvents();
3466 rightWindow->assertNoEvents();
3467}
3468
3469/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003470 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3471 * While the touch is down, new hover events from the stylus device should be ignored. After the
3472 * touch is gone, stylus hovering should start working again.
3473 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003474TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003475 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003476 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003477 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3478 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003479 window->setFrame(Rect(0, 0, 200, 200));
3480
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003481 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003482
3483 const int32_t stylusDeviceId = 5;
3484 const int32_t touchDeviceId = 4;
3485 // Start hovering with stylus
3486 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003487 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003488 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003489 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003490 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003491 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003492 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003493
3494 // Finger down on the window
3495 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003496 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003497 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003498 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003499 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003500 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003501 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003502
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003503 // Continue hovering with stylus.
3504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003505 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003506 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3507 AINPUT_SOURCE_STYLUS)
3508 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003509 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003510 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003511 // Hovers continue to work
3512 window->consumeMotionEvent(
3513 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003514
3515 // Lift up the finger
3516 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003517 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003518 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3519 AINPUT_SOURCE_TOUCHSCREEN)
3520 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003521 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003522 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003523
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003524 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003525 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003526 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3527 AINPUT_SOURCE_STYLUS)
3528 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003529 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003530 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003531 window->consumeMotionEvent(
3532 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003533 window->assertNoEvents();
3534}
3535
3536/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003537 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3538 * While the touch is down, hovering from the stylus is not affected. After the touch is gone,
3539 * check that the stylus hovering continues to work.
3540 */
3541TEST_F(InputDispatcherMultiDeviceTest, StylusHoverWithTouchTap) {
3542 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3543 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003544 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3545 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003546 window->setFrame(Rect(0, 0, 200, 200));
3547
3548 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3549
3550 const int32_t stylusDeviceId = 5;
3551 const int32_t touchDeviceId = 4;
3552 // Start hovering with stylus
3553 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3554 .deviceId(stylusDeviceId)
3555 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3556 .build());
3557 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3558
3559 // Finger down on the window
3560 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3561 .deviceId(touchDeviceId)
3562 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3563 .build());
3564 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3565
3566 // Continue hovering with stylus.
3567 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3568 .deviceId(stylusDeviceId)
3569 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
3570 .build());
3571 // Hovers continue to work
3572 window->consumeMotionEvent(
3573 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3574
3575 // Lift up the finger
3576 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3577 .deviceId(touchDeviceId)
3578 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3579 .build());
3580 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
3581
3582 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3583 .deviceId(stylusDeviceId)
3584 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
3585 .build());
3586 window->consumeMotionEvent(
3587 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3588 window->assertNoEvents();
3589}
3590
3591/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003592 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3593 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3594 *
3595 * Two windows: one on the left and one on the right.
3596 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3597 * Stylus down on the left window, and then touch down on the right window.
3598 * Check that the right window doesn't get touches while the stylus is down on the left window.
3599 */
3600TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3601 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3602 sp<FakeWindowHandle> leftWindow =
3603 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003604 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003605 leftWindow->setFrame(Rect(0, 0, 100, 100));
3606
3607 sp<FakeWindowHandle> sbtRightWindow =
3608 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003609 "Stylus blocks touch (right) window",
3610 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003611 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3612 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3613
3614 mDispatcher->onWindowInfosChanged(
3615 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3616
3617 const int32_t stylusDeviceId = 5;
3618 const int32_t touchDeviceId = 4;
3619
3620 // Stylus down in the left window
3621 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3622 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3623 .deviceId(stylusDeviceId)
3624 .build());
3625 leftWindow->consumeMotionEvent(
3626 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3627
3628 // Finger tap on the right window
3629 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3630 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3631 .deviceId(touchDeviceId)
3632 .build());
3633 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3634 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3635 .deviceId(touchDeviceId)
3636 .build());
3637
3638 // The touch should be blocked, because stylus is down somewhere else on screen!
3639 sbtRightWindow->assertNoEvents();
3640
3641 // Continue stylus motion, and ensure it's not impacted.
3642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3643 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3644 .deviceId(stylusDeviceId)
3645 .build());
3646 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3647 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3648 .deviceId(stylusDeviceId)
3649 .build());
3650 leftWindow->consumeMotionEvent(
3651 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3652 leftWindow->consumeMotionEvent(
3653 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3654
3655 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3656 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3657 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3658 .deviceId(touchDeviceId)
3659 .build());
3660 sbtRightWindow->consumeMotionEvent(
3661 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3662}
3663
3664/**
3665 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3666 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3667 *
3668 * Two windows: one on the left and one on the right.
3669 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3670 * Stylus hover on the left window, and then touch down on the right window.
3671 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3672 */
3673TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3674 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3675 sp<FakeWindowHandle> leftWindow =
3676 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003677 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003678 leftWindow->setFrame(Rect(0, 0, 100, 100));
3679
3680 sp<FakeWindowHandle> sbtRightWindow =
3681 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003682 "Stylus blocks touch (right) window",
3683 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003684 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3685 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3686
3687 mDispatcher->onWindowInfosChanged(
3688 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3689
3690 const int32_t stylusDeviceId = 5;
3691 const int32_t touchDeviceId = 4;
3692
3693 // Stylus hover in the left window
3694 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3695 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3696 .deviceId(stylusDeviceId)
3697 .build());
3698 leftWindow->consumeMotionEvent(
3699 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3700
3701 // Finger tap on the right window
3702 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3703 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3704 .deviceId(touchDeviceId)
3705 .build());
3706 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3707 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3708 .deviceId(touchDeviceId)
3709 .build());
3710
3711 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3712 sbtRightWindow->assertNoEvents();
3713
3714 // Continue stylus motion, and ensure it's not impacted.
3715 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3716 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3717 .deviceId(stylusDeviceId)
3718 .build());
3719 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3720 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3721 .deviceId(stylusDeviceId)
3722 .build());
3723 leftWindow->consumeMotionEvent(
3724 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3725 leftWindow->consumeMotionEvent(
3726 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3727
3728 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3729 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3730 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3731 .deviceId(touchDeviceId)
3732 .build());
3733 sbtRightWindow->consumeMotionEvent(
3734 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3735}
3736
3737/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003738 * A spy window above a window with no input channel.
3739 * Start hovering with a stylus device, and then tap with it.
3740 * Ensure spy window receives the entire sequence.
3741 */
3742TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3743 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003744 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3745 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003746 spyWindow->setFrame(Rect(0, 0, 200, 200));
3747 spyWindow->setTrustedOverlay(true);
3748 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003749 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3750 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003751 window->setNoInputChannel(true);
3752 window->setFrame(Rect(0, 0, 200, 200));
3753
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003754 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003755
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003756 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3758 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3759 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003760 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3761 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003762 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3763 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3764 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003765 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3766
3767 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003768 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3769 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3770 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003771 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3772
3773 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003774 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3775 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3776 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003777 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3778
3779 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003780 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3781 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3782 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003783 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3784 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003785 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, 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_EXIT));
3789
3790 // No more events
3791 spyWindow->assertNoEvents();
3792 window->assertNoEvents();
3793}
3794
3795/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003796 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3797 * rejected. But since we already have an ongoing gesture, this event should be processed.
3798 * This prevents inconsistent events being handled inside the dispatcher.
3799 */
3800TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3801 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3802
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003803 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3804 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003805 window->setFrame(Rect(0, 0, 200, 200));
3806
3807 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3808
3809 // Start hovering with stylus
3810 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3811 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3812 .build());
3813 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3814
3815 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3816 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3817 .build();
3818 // Make this 'hoverExit' event stale
3819 mFakePolicy->setStaleEventTimeout(100ms);
3820 std::this_thread::sleep_for(100ms);
3821
3822 // It shouldn't be dropped by the dispatcher, even though it's stale.
3823 mDispatcher->notifyMotion(hoverExit);
3824 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3825
3826 // Stylus starts hovering again! There should be no crash.
3827 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3828 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3829 .build());
3830 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3831}
3832
3833/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003834 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3835 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3836 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3837 * While the mouse is down, new move events from the touch device should be ignored.
3838 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003839TEST_F(InputDispatcherTest, TouchPilferAndMouseMove_legacy) {
3840 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003842 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3843 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003844 spyWindow->setFrame(Rect(0, 0, 200, 200));
3845 spyWindow->setTrustedOverlay(true);
3846 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003847 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3848 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003849 window->setFrame(Rect(0, 0, 200, 200));
3850
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003851 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003852
3853 const int32_t mouseDeviceId = 7;
3854 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003855
3856 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003857 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3858 .deviceId(mouseDeviceId)
3859 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3860 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003861 spyWindow->consumeMotionEvent(
3862 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3863 window->consumeMotionEvent(
3864 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3865
3866 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003867 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3868 .deviceId(touchDeviceId)
3869 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3870 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003871 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3872 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3873 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3874 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3875
Prabir Pradhan678438e2023-04-13 19:32:51 +00003876 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3877 .deviceId(touchDeviceId)
3878 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3879 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003880 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3881 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3882
3883 // Pilfer the stream
3884 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3885 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3886
Prabir Pradhan678438e2023-04-13 19:32:51 +00003887 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3888 .deviceId(touchDeviceId)
3889 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3890 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003891 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3892
3893 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003894 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3895 .deviceId(mouseDeviceId)
3896 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3897 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3898 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003899
3900 spyWindow->consumeMotionEvent(
3901 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3902 spyWindow->consumeMotionEvent(
3903 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3904 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3905
Prabir Pradhan678438e2023-04-13 19:32:51 +00003906 mDispatcher->notifyMotion(
3907 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3908 .deviceId(mouseDeviceId)
3909 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3910 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3911 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3912 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003913 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3914 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3915
3916 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003917 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3918 .deviceId(mouseDeviceId)
3919 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3920 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3921 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003922 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3923 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3924
3925 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003926 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3927 .deviceId(touchDeviceId)
3928 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3929 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003930
3931 // No more events
3932 spyWindow->assertNoEvents();
3933 window->assertNoEvents();
3934}
3935
3936/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003937 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3938 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3939 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3940 * While the mouse is down, new move events from the touch device should continue to work.
3941 */
3942TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3943 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3944 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003945 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3946 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003947 spyWindow->setFrame(Rect(0, 0, 200, 200));
3948 spyWindow->setTrustedOverlay(true);
3949 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003950 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3951 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003952 window->setFrame(Rect(0, 0, 200, 200));
3953
3954 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
3955
3956 const int32_t mouseDeviceId = 7;
3957 const int32_t touchDeviceId = 4;
3958
3959 // Hover a bit with mouse first
3960 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3961 .deviceId(mouseDeviceId)
3962 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3963 .build());
3964 spyWindow->consumeMotionEvent(
3965 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3966 window->consumeMotionEvent(
3967 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3968
3969 // Start touching
3970 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3971 .deviceId(touchDeviceId)
3972 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3973 .build());
3974
3975 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3976 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3977
3978 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3979 .deviceId(touchDeviceId)
3980 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3981 .build());
3982 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3983 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3984
3985 // Pilfer the stream
3986 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3987 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3988 // Hover is not pilfered! Only touch.
3989
3990 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3991 .deviceId(touchDeviceId)
3992 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3993 .build());
3994 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3995
3996 // Mouse down
3997 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3998 .deviceId(mouseDeviceId)
3999 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4000 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4001 .build());
4002
4003 spyWindow->consumeMotionEvent(
4004 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4005 spyWindow->consumeMotionEvent(
4006 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4007 window->consumeMotionEvent(
4008 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4009 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4010
4011 mDispatcher->notifyMotion(
4012 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4013 .deviceId(mouseDeviceId)
4014 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4015 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4016 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4017 .build());
4018 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4019 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4020
4021 // Mouse move!
4022 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4023 .deviceId(mouseDeviceId)
4024 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4025 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4026 .build());
4027 spyWindow->consumeMotionEvent(
4028 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4029 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4030
4031 // Touch move!
4032 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4033 .deviceId(touchDeviceId)
4034 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4035 .build());
4036 spyWindow->consumeMotionEvent(
4037 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4038
4039 // No more events
4040 spyWindow->assertNoEvents();
4041 window->assertNoEvents();
4042}
4043
4044/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004045 * On the display, have a single window, and also an area where there's no window.
4046 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
4047 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
4048 */
4049TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
4050 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4051 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004052 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004053
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004054 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004055
4056 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00004057 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004058
4059 mDispatcher->waitForIdle();
4060 window->assertNoEvents();
4061
4062 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004063 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004064 mDispatcher->waitForIdle();
4065 window->consumeMotionDown();
4066}
4067
4068/**
4069 * Same test as above, but instead of touching the empty space, the first touch goes to
4070 * non-touchable window.
4071 */
4072TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
4073 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4074 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004075 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004076 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4077 window1->setTouchable(false);
4078 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004079 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004080 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4081
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004082 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004083
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004084 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004085 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004086
4087 mDispatcher->waitForIdle();
4088 window1->assertNoEvents();
4089 window2->assertNoEvents();
4090
4091 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004092 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004093 mDispatcher->waitForIdle();
4094 window2->consumeMotionDown();
4095}
4096
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004097/**
4098 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
4099 * to the event time of the first ACTION_DOWN sent to the particular window.
4100 */
4101TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
4102 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4103 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004104 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004105 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4106 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004107 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004108 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4109
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004110 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004111
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004112 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004113 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004114 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004115
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004116 const std::unique_ptr<MotionEvent> firstDown =
4117 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4118 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004119 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004120
4121 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004122 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004123 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004124
4125 const std::unique_ptr<MotionEvent> secondDown =
4126 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4127 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
4128 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
4129 // We currently send MOVE events to all windows receiving a split touch when there is any change
4130 // in the touch state, even when none of the pointers in the split window actually moved.
4131 // Document this behavior in the test.
4132 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004133
4134 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004135 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004136 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004137
4138 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4139 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004140
4141 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004142 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004143 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004144
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004145 window2->consumeMotionEvent(
4146 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
4147 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004148
4149 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004150 mDispatcher->notifyMotion(
4151 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004152 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004153
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004154 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
4155 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4156
4157 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004158 mDispatcher->notifyMotion(
4159 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004160 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004161
4162 window1->consumeMotionEvent(
4163 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
4164 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004165}
4166
Siarhei Vishniakouac42d242024-06-28 10:43:53 -07004167/**
4168 * When events are not split, the downTime should be adjusted such that the downTime corresponds
4169 * to the event time of the first ACTION_DOWN. If a new window appears, it should not affect
4170 * the event routing because the first window prevents splitting.
4171 */
4172TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTimeForNewWindow) {
4173 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4174 sp<FakeWindowHandle> window1 =
4175 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4176 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4177 window1->setPreventSplitting(true);
4178
4179 sp<FakeWindowHandle> window2 =
4180 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4181 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4182
4183 mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4184
4185 // Touch down on the first window
4186 NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4187 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4188 .build();
4189 mDispatcher->notifyMotion(downArgs);
4190
4191 window1->consumeMotionEvent(
4192 AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4193
4194 // Second window is added
4195 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4196
4197 // Now touch down on the window with another pointer
4198 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4199 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4200 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4201 .downTime(downArgs.downTime)
4202 .build());
4203 window1->consumeMotionPointerDown(1, AllOf(WithDownTime(downArgs.downTime)));
4204
4205 // Finish the gesture
4206 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4207 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4208 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4209 .downTime(downArgs.downTime)
4210 .build());
4211 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4212 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4213 .downTime(downArgs.downTime)
4214 .build());
4215 window1->consumeMotionPointerUp(1, AllOf(WithDownTime(downArgs.downTime)));
4216 window1->consumeMotionEvent(
4217 AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4218 window2->assertNoEvents();
4219}
4220
4221/**
4222 * When splitting touch events, the downTime should be adjusted such that the downTime corresponds
4223 * to the event time of the first ACTION_DOWN sent to the new window.
4224 * If a new window that does not support split appears on the screen and gets touched with the
4225 * second finger, it should not get any events because it doesn't want split touches. At the same
4226 * time, the first window should not get the pointer_down event because it supports split touches
4227 * (and the touch occurred outside of the bounds of window1).
4228 */
4229TEST_F(InputDispatcherTest, SplitTouchesDropsEventForNonSplittableSecondWindow) {
4230 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4231 sp<FakeWindowHandle> window1 =
4232 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4233 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4234
4235 sp<FakeWindowHandle> window2 =
4236 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4237 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4238
4239 mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4240
4241 // Touch down on the first window
4242 NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4243 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4244 .build();
4245 mDispatcher->notifyMotion(downArgs);
4246
4247 window1->consumeMotionEvent(
4248 AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4249
4250 // Second window is added
4251 window2->setPreventSplitting(true);
4252 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4253
4254 // Now touch down on the window with another pointer
4255 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4256 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4257 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4258 .downTime(downArgs.downTime)
4259 .build());
4260 // Event is dropped because window2 doesn't support split touch, and window1 does.
4261
4262 // Complete the gesture
4263 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4264 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4265 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4266 .downTime(downArgs.downTime)
4267 .build());
4268 // A redundant MOVE event is generated that doesn't carry any new information
4269 window1->consumeMotionEvent(
4270 AllOf(WithMotionAction(ACTION_MOVE), WithDownTime(downArgs.downTime)));
4271 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4272 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4273 .downTime(downArgs.downTime)
4274 .build());
4275
4276 window1->consumeMotionEvent(
4277 AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4278 window1->assertNoEvents();
4279 window2->assertNoEvents();
4280}
4281
Garfield Tandf26e862020-07-01 20:18:19 -07004282TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004283 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004284 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4285 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004286 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004287 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4288 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004289 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004290
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004291 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004292
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004293 mDispatcher->onWindowInfosChanged(
4294 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004295
4296 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004298 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004299 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4300 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004301 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004302 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004303 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004304
4305 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004307 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004308 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4309 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004310 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004311 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004312 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4313 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004314
4315 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004317 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004318 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4319 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004320 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004321 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004322 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4323 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004324
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004326 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004327 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4328 AINPUT_SOURCE_MOUSE)
4329 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4330 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004331 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004332 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004333 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004334
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004336 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004337 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4338 AINPUT_SOURCE_MOUSE)
4339 .buttonState(0)
4340 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004341 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004342 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004343 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004344
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004346 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004347 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4348 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004349 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004350 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004351 windowLeft->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004352
4353 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004355 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004356 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4357 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004358 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004359 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004360 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004361
4362 // No more events
4363 windowLeft->assertNoEvents();
4364 windowRight->assertNoEvents();
4365}
4366
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004367/**
4368 * Put two fingers down (and don't release them) and click the mouse button.
4369 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4370 * currently active gesture should be canceled, and the new one should proceed.
4371 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004372TEST_F(InputDispatcherTest, TwoPointersDownMouseClick_legacy) {
4373 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004375 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4376 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004377 window->setFrame(Rect(0, 0, 600, 800));
4378
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004379 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004380
4381 const int32_t touchDeviceId = 4;
4382 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004383
4384 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004385 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4386 .deviceId(touchDeviceId)
4387 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4388 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004389
Prabir Pradhan678438e2023-04-13 19:32:51 +00004390 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4391 .deviceId(touchDeviceId)
4392 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4393 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4394 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004395 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4396 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4397
4398 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4400 .deviceId(mouseDeviceId)
4401 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4402 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4403 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004404 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4405 WithPointerCount(2u)));
4406 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4407
Prabir Pradhan678438e2023-04-13 19:32:51 +00004408 mDispatcher->notifyMotion(
4409 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4410 .deviceId(mouseDeviceId)
4411 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4412 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4413 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4414 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004415 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4416
4417 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4418 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004419 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4420 .deviceId(touchDeviceId)
4421 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4422 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4423 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004424 window->assertNoEvents();
4425}
4426
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004427/**
4428 * Put two fingers down (and don't release them) and click the mouse button.
4429 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4430 * currently active gesture should not be canceled, and the new one should proceed in parallel.
4431 */
4432TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4433 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4434 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004435 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4436 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004437 window->setFrame(Rect(0, 0, 600, 800));
4438
4439 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4440
4441 const int32_t touchDeviceId = 4;
4442 const int32_t mouseDeviceId = 6;
4443
4444 // Two pointers down
4445 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4446 .deviceId(touchDeviceId)
4447 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4448 .build());
4449
4450 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4451 .deviceId(touchDeviceId)
4452 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4453 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4454 .build());
4455 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4456 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4457
4458 // Send a series of mouse events for a mouse click
4459 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4460 .deviceId(mouseDeviceId)
4461 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4462 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4463 .build());
4464 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4465
4466 mDispatcher->notifyMotion(
4467 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4468 .deviceId(mouseDeviceId)
4469 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4470 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4471 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4472 .build());
4473 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4474
4475 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4476 // already active gesture, it should be sent normally.
4477 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4478 .deviceId(touchDeviceId)
4479 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4480 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4481 .build());
4482 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4483 window->assertNoEvents();
4484}
4485
Siarhei Vishniakou07cdda92024-07-01 16:45:08 -07004486/**
4487 * A spy window sits above a window with NO_INPUT_CHANNEL. Ensure that the spy receives events even
4488 * though the window underneath should not get any events.
4489 */
4490TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowSinglePointer) {
4491 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4492
4493 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4494 ui::LogicalDisplayId::DEFAULT);
4495 spyWindow->setFrame(Rect(0, 0, 100, 100));
4496 spyWindow->setTrustedOverlay(true);
4497 spyWindow->setPreventSplitting(true);
4498 spyWindow->setSpy(true);
4499 // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4500 sp<FakeWindowHandle> inputSinkWindow =
4501 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4502 ui::LogicalDisplayId::DEFAULT);
4503 inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
4504 inputSinkWindow->setTrustedOverlay(true);
4505 inputSinkWindow->setPreventSplitting(true);
4506 inputSinkWindow->setNoInputChannel(true);
4507
4508 mDispatcher->onWindowInfosChanged(
4509 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo()}, {}, 0, 0});
4510
4511 // Tap the spy window
4512 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4513 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(51))
4514 .build());
4515 mDispatcher->notifyMotion(
4516 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4517 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4518 .build());
4519
4520 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4521 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP)));
4522 inputSinkWindow->assertNoEvents();
4523}
4524
4525/**
4526 * A spy window sits above a window with NO_INPUT_CHANNEL. Ensure that the spy receives events even
4527 * though the window underneath should not get any events.
4528 * Same test as above, but with two pointers touching instead of one.
4529 */
4530TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowTwoPointers) {
4531 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4532
4533 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4534 ui::LogicalDisplayId::DEFAULT);
4535 spyWindow->setFrame(Rect(0, 0, 100, 100));
4536 spyWindow->setTrustedOverlay(true);
4537 spyWindow->setPreventSplitting(true);
4538 spyWindow->setSpy(true);
4539 // Another window below spy that would have both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4540 sp<FakeWindowHandle> inputSinkWindow =
4541 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4542 ui::LogicalDisplayId::DEFAULT);
4543 inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
4544 inputSinkWindow->setTrustedOverlay(true);
4545 inputSinkWindow->setPreventSplitting(true);
4546 inputSinkWindow->setNoInputChannel(true);
4547
4548 mDispatcher->onWindowInfosChanged(
4549 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo()}, {}, 0, 0});
4550
4551 // Both fingers land into the spy window
4552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4553 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(51))
4554 .build());
4555 mDispatcher->notifyMotion(
4556 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4557 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4558 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(11))
4559 .build());
4560 mDispatcher->notifyMotion(
4561 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4562 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4563 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(11))
4564 .build());
4565 mDispatcher->notifyMotion(
4566 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4567 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4568 .build());
4569
4570 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4571 spyWindow->consumeMotionPointerDown(1, WithPointerCount(2));
4572 spyWindow->consumeMotionPointerUp(1, WithPointerCount(2));
4573 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP)));
4574 inputSinkWindow->assertNoEvents();
4575}
4576
4577/** Check the behaviour for cases where input sink prevents or doesn't prevent splitting. */
4578class SpyThatPreventsSplittingWithApplicationFixture : public InputDispatcherTest,
4579 public ::testing::WithParamInterface<bool> {
4580};
4581
4582/**
4583 * Three windows:
4584 * - An application window (app window)
4585 * - A spy window that does not overlap the app window. Has PREVENT_SPLITTING flag
4586 * - A window below the spy that has NO_INPUT_CHANNEL (call it 'inputSink')
4587 *
4588 * The spy window is side-by-side with the app window. The inputSink is below the spy.
4589 * We first touch the area outside of the appWindow, but inside spyWindow.
4590 * Only the SPY window should get the DOWN event.
4591 * The spy pilfers after receiving the first DOWN event.
4592 * Next, we touch the app window.
4593 * The spy should receive POINTER_DOWN(1) (since spy is preventing splits).
4594 * Also, since the spy is already pilfering the first pointer, it will be sent the remaining new
4595 * pointers automatically, as well.
4596 * Next, the first pointer (from the spy) is lifted.
4597 * Spy should get POINTER_UP(0).
4598 * This event should not go to the app because the app never received this pointer to begin with.
4599 * Now, lift the remaining pointer and check that the spy receives UP event.
4600 *
4601 * Finally, send a new ACTION_DOWN event to the spy and check that it's received.
4602 * This test attempts to reproduce a crash in the dispatcher.
4603 */
4604TEST_P(SpyThatPreventsSplittingWithApplicationFixture, SpyThatPreventsSplittingWithApplication) {
4605 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4606
4607 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4608 ui::LogicalDisplayId::DEFAULT);
4609 spyWindow->setFrame(Rect(100, 100, 200, 200));
4610 spyWindow->setTrustedOverlay(true);
4611 spyWindow->setPreventSplitting(true);
4612 spyWindow->setSpy(true);
4613 // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4614 sp<FakeWindowHandle> inputSinkWindow =
4615 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4616 ui::LogicalDisplayId::DEFAULT);
4617 inputSinkWindow->setFrame(Rect(100, 100, 200, 200)); // directly below the spy
4618 inputSinkWindow->setTrustedOverlay(true);
4619 inputSinkWindow->setPreventSplitting(GetParam());
4620 inputSinkWindow->setNoInputChannel(true);
4621
4622 sp<FakeWindowHandle> appWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "App",
4623 ui::LogicalDisplayId::DEFAULT);
4624 appWindow->setFrame(Rect(0, 0, 100, 100));
4625
4626 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
4627 mDispatcher->onWindowInfosChanged(
4628 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo(), *appWindow->getInfo()},
4629 {},
4630 0,
4631 0});
4632
4633 // First finger lands outside of the appWindow, but inside of the spy window
4634 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4635 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
4636 .build());
4637 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4638
4639 mDispatcher->pilferPointers(spyWindow->getToken());
4640
4641 // Second finger lands in the app, and goes to the spy window. It doesn't go to the app because
4642 // the spy is already pilfering the first pointer, and this automatically grants the remaining
4643 // new pointers to the spy, as well.
4644 mDispatcher->notifyMotion(
4645 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4646 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
4647 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4648 .build());
4649
4650 spyWindow->consumeMotionPointerDown(1, WithPointerCount(2));
4651
4652 // Now lift up the first pointer
4653 mDispatcher->notifyMotion(
4654 MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
4655 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
4656 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4657 .build());
4658 spyWindow->consumeMotionPointerUp(0, WithPointerCount(2));
4659
4660 // And lift the remaining pointer!
4661 mDispatcher->notifyMotion(
4662 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4663 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4664 .build());
4665 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithPointerCount(1)));
4666
4667 // Now send a new DOWN, which should again go to spy.
4668 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4669 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
4670 .build());
4671 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4672 // The app window doesn't get any events this entire time because the spy received the events
4673 // first and pilfered, which makes all new pointers go to it as well.
4674 appWindow->assertNoEvents();
4675}
4676
4677// Behaviour should be the same regardless of whether inputSink supports splitting.
4678INSTANTIATE_TEST_SUITE_P(SpyThatPreventsSplittingWithApplication,
4679 SpyThatPreventsSplittingWithApplicationFixture, testing::Bool());
4680
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004681TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4682 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4683
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004684 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4685 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004686 spyWindow->setFrame(Rect(0, 0, 600, 800));
4687 spyWindow->setTrustedOverlay(true);
4688 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004689 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4690 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004691 window->setFrame(Rect(0, 0, 600, 800));
4692
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004693 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004694 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004695
4696 // Send mouse cursor to the window
4697 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004698 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004699 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4700 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004701 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004702 .build()));
4703
4704 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4705 WithSource(AINPUT_SOURCE_MOUSE)));
4706 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4707 WithSource(AINPUT_SOURCE_MOUSE)));
4708
4709 window->assertNoEvents();
4710 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004711}
4712
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004713TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows_legacy) {
4714 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004715 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4716
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004717 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4718 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004719 spyWindow->setFrame(Rect(0, 0, 600, 800));
4720 spyWindow->setTrustedOverlay(true);
4721 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004722 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4723 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004724 window->setFrame(Rect(0, 0, 600, 800));
4725
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004726 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004727 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004728
4729 // Send mouse cursor to the window
4730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004731 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004732 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4733 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004734 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004735 .build()));
4736
4737 // Move mouse cursor
4738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004739 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004740 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4741 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004742 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004743 .build()));
4744
4745 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4746 WithSource(AINPUT_SOURCE_MOUSE)));
4747 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4748 WithSource(AINPUT_SOURCE_MOUSE)));
4749 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4750 WithSource(AINPUT_SOURCE_MOUSE)));
4751 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4752 WithSource(AINPUT_SOURCE_MOUSE)));
4753 // Touch down on the window
4754 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004755 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004756 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4757 AINPUT_SOURCE_TOUCHSCREEN)
4758 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004759 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004760 .build()));
4761 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4762 WithSource(AINPUT_SOURCE_MOUSE)));
4763 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4764 WithSource(AINPUT_SOURCE_MOUSE)));
4765 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4766 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4767 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4768 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4769
4770 // pilfer the motion, retaining the gesture on the spy window.
4771 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4772 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4773 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4774
4775 // Touch UP on the window
4776 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004777 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004778 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4779 AINPUT_SOURCE_TOUCHSCREEN)
4780 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004781 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004782 .build()));
4783 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4784 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4785
4786 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4787 // to send a new gesture. It should again go to both windows (spy and the window below), just
4788 // like the first gesture did, before pilfering. The window configuration has not changed.
4789
4790 // One more tap - DOWN
4791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004792 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004793 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4794 AINPUT_SOURCE_TOUCHSCREEN)
4795 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004796 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004797 .build()));
4798 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4799 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4800 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4801 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4802
4803 // Touch UP on the window
4804 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004805 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004806 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4807 AINPUT_SOURCE_TOUCHSCREEN)
4808 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004809 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004810 .build()));
4811 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4812 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4813 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4814 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4815
4816 window->assertNoEvents();
4817 spyWindow->assertNoEvents();
4818}
4819
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004820TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4821 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4822 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4823
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004824 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4825 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004826 spyWindow->setFrame(Rect(0, 0, 600, 800));
4827 spyWindow->setTrustedOverlay(true);
4828 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004829 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4830 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004831 window->setFrame(Rect(0, 0, 600, 800));
4832
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004833 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004834 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4835
4836 // Send mouse cursor to the window
4837 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4838 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4839 .build());
4840
4841 // Move mouse cursor
4842 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4843 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4844 .build());
4845
4846 window->consumeMotionEvent(
4847 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4848 spyWindow->consumeMotionEvent(
4849 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4850 window->consumeMotionEvent(
4851 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4852 spyWindow->consumeMotionEvent(
4853 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4854 // Touch down on the window
4855 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4856 .deviceId(SECOND_DEVICE_ID)
4857 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4858 .build());
4859 window->consumeMotionEvent(
4860 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4861 spyWindow->consumeMotionEvent(
4862 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4863
4864 // pilfer the motion, retaining the gesture on the spy window.
4865 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4866 window->consumeMotionEvent(
4867 AllOf(WithMotionAction(ACTION_CANCEL), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4868 // Mouse hover is not pilfered
4869
4870 // Touch UP on the window
4871 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4872 .deviceId(SECOND_DEVICE_ID)
4873 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4874 .build());
4875 spyWindow->consumeMotionEvent(
4876 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4877
4878 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4879 // to send a new gesture. It should again go to both windows (spy and the window below), just
4880 // like the first gesture did, before pilfering. The window configuration has not changed.
4881
4882 // One more tap - DOWN
4883 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4884 .deviceId(SECOND_DEVICE_ID)
4885 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4886 .build());
4887 window->consumeMotionEvent(
4888 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4889 spyWindow->consumeMotionEvent(
4890 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4891
4892 // Touch UP on the window
4893 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4894 .deviceId(SECOND_DEVICE_ID)
4895 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4896 .build());
4897 window->consumeMotionEvent(
4898 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4899 spyWindow->consumeMotionEvent(
4900 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4901
4902 // Mouse movement continues normally as well
4903 // Move mouse cursor
4904 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4905 .pointer(PointerBuilder(0, ToolType::MOUSE).x(120).y(130))
4906 .build());
4907 window->consumeMotionEvent(
4908 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4909 spyWindow->consumeMotionEvent(
4910 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4911
4912 window->assertNoEvents();
4913 spyWindow->assertNoEvents();
4914}
4915
Garfield Tandf26e862020-07-01 20:18:19 -07004916// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4917// directly in this test.
4918TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004919 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004920 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4921 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004922 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004923
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004924 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004925
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004926 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004927
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004928 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004929 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004930 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4931 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004932 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004933 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004934 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004935 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004936 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004937 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004938 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4939 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004940 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004941 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004942 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4943 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004944
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004946 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004947 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4948 AINPUT_SOURCE_MOUSE)
4949 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4950 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004951 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004952 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004953 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004954
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004956 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004957 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4958 AINPUT_SOURCE_MOUSE)
4959 .buttonState(0)
4960 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004961 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004962 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004963 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004964
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004965 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004966 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004967 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4968 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004969 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004970 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004971 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004972
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004973 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4974 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4975 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004976 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004977 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4978 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004979 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004980 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004981 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004982}
4983
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004984/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004985 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4986 * is generated.
4987 */
4988TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4989 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004990 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4991 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004992 window->setFrame(Rect(0, 0, 1200, 800));
4993
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004994 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004995
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004996 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004997
4998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004999 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005000 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
5001 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005002 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005003 .build()));
5004 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5005
5006 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005007 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005008 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
5009}
5010
5011/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07005012 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
5013 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00005014TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
5015 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
5016 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07005017 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005018 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5019 ui::LogicalDisplayId::DEFAULT);
Daniel Norman7487dfa2023-08-02 16:39:45 -07005020 window->setFrame(Rect(0, 0, 1200, 800));
5021
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005022 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Daniel Norman7487dfa2023-08-02 16:39:45 -07005023
5024 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5025
5026 MotionEventBuilder hoverEnterBuilder =
5027 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5028 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
5029 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
5030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5031 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
5032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5033 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
5034 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5035 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5036}
5037
5038/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005039 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
5040 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005041TEST_F(InputDispatcherTest, TouchDownAfterMouseHover_legacy) {
5042 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005043 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005044 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5045 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005046 window->setFrame(Rect(0, 0, 100, 100));
5047
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005048 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005049
5050 const int32_t mouseDeviceId = 7;
5051 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005052
5053 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00005054 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5055 .deviceId(mouseDeviceId)
5056 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
5057 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005058 window->consumeMotionEvent(
5059 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
5060
5061 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00005062 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5063 .deviceId(touchDeviceId)
5064 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5065 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005066
5067 window->consumeMotionEvent(
5068 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
5069 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
5070}
5071
5072/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005073 * If mouse is hovering when the touch goes down, the hovering should not be stopped.
5074 */
5075TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
5076 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5077 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005078 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5079 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005080 window->setFrame(Rect(0, 0, 100, 100));
5081
5082 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5083
5084 const int32_t mouseDeviceId = 7;
5085 const int32_t touchDeviceId = 4;
5086
5087 // Start hovering with the mouse
5088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5089 .deviceId(mouseDeviceId)
5090 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
5091 .build());
5092 window->consumeMotionEvent(
5093 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
5094
5095 // Touch goes down
5096 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5097 .deviceId(touchDeviceId)
5098 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5099 .build());
5100 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
5101}
5102
5103/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005104 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005105 * The tap causes a HOVER_EXIT event to be generated because the current event
5106 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005107 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005108TEST_F(InputDispatcherTest, MouseHoverAndTouchTap_legacy) {
5109 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005110 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005111 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5112 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005113 window->setFrame(Rect(0, 0, 100, 100));
5114
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005115 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005116 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
5117 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
5118 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005119 ASSERT_NO_FATAL_FAILURE(
5120 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
5121 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005122
5123 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005124 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5125 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5126 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005127 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005128 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
5129 WithSource(AINPUT_SOURCE_MOUSE))));
5130
5131 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005132 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
5133 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
5134
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005135 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5136 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5137 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005138 ASSERT_NO_FATAL_FAILURE(
5139 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
5140 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
5141}
5142
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005143/**
5144 * Send a mouse hover event followed by a tap from touchscreen.
5145 * The tap causes a HOVER_EXIT event to be generated because the current event
5146 * stream's source has been switched.
5147 */
5148TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
5149 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5150 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005151 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5152 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005153 window->setFrame(Rect(0, 0, 100, 100));
5154
5155 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5156 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
5157 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
5158 .build());
5159
5160 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
5161 WithSource(AINPUT_SOURCE_MOUSE)));
5162
5163 // Tap on the window
5164 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5165 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5166 .build());
5167
5168 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
5169 WithSource(AINPUT_SOURCE_MOUSE)));
5170
5171 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
5172 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
5173
5174 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5175 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5176 .build());
5177
5178 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
5179 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
5180}
5181
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005182TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
5183 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5184 sp<FakeWindowHandle> windowDefaultDisplay =
5185 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005186 ui::LogicalDisplayId::DEFAULT);
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005187 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
5188 sp<FakeWindowHandle> windowSecondDisplay =
5189 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
5190 SECOND_DISPLAY_ID);
5191 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
5192
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005193 mDispatcher->onWindowInfosChanged(
5194 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005195
5196 // Set cursor position in window in default display and check that hover enter and move
5197 // events are generated.
5198 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005199 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005200 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5201 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005202 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005203 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005204 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005205 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005206
5207 // Remove all windows in secondary display and check that no event happens on window in
5208 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005209 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
5210
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005211 windowDefaultDisplay->assertNoEvents();
5212
5213 // Move cursor position in window in default display and check that only hover move
5214 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005215 mDispatcher->onWindowInfosChanged(
5216 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005218 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005219 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5220 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005221 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005222 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005223 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005224 windowDefaultDisplay->consumeMotionEvent(
5225 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
5226 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005227 windowDefaultDisplay->assertNoEvents();
5228}
5229
Garfield Tan00f511d2019-06-12 16:55:40 -07005230TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07005231 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07005232
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005233 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
5234 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005235 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005236 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
5237 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005238 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07005239
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005240 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tan00f511d2019-06-12 16:55:40 -07005241
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005242 mDispatcher->onWindowInfosChanged(
5243 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07005244
5245 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
5246 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005248 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005249 ui::LogicalDisplayId::DEFAULT, {610, 400}, {599, 400}));
5250 windowLeft->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005251 windowRight->assertNoEvents();
5252}
5253
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005254TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005255 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005256 sp<FakeWindowHandle> window =
5257 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5258 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07005259 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005260
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005261 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005262 setFocusedWindow(window);
5263
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005264 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005265
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005266 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005267
5268 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005269 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005270
5271 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
5272 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005273 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005274 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005275}
5276
5277TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005278 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005279 sp<FakeWindowHandle> window =
5280 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5281 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005282
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005283 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005284
Prabir Pradhan678438e2023-04-13 19:32:51 +00005285 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005286 AINPUT_SOURCE_TOUCHSCREEN,
5287 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005288
5289 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005290 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005291
5292 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
5293 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005294 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005295 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005296 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005297}
5298
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005299TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
5300 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005301 sp<FakeWindowHandle> window =
5302 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5303 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005304
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005305 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005306
5307 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5308 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
5309 .build());
5310
5311 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5312
5313 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
5314 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
5315 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5316
5317 // After the device has been reset, a new hovering stream can be sent to the window
5318 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5319 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
5320 .build());
5321 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5322}
5323
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005324TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
5325 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005326 sp<FakeWindowHandle> window =
5327 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5328 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005329 window->setFocusable(true);
5330
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005331 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005332 setFocusedWindow(window);
5333
5334 window->consumeFocusEvent(true);
5335
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005336 const NotifyKeyArgs keyArgs =
5337 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005338 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
5339 const nsecs_t injectTime = keyArgs.eventTime;
5340 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005341 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005342 // The dispatching time should be always greater than or equal to intercept key timeout.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005343 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005344 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
5345 std::chrono::nanoseconds(interceptKeyTimeout).count());
5346}
5347
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005348/**
5349 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
5350 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005351TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
5352 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005353 sp<FakeWindowHandle> window =
5354 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5355 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005356 window->setFocusable(true);
5357
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005358 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005359 setFocusedWindow(window);
5360
5361 window->consumeFocusEvent(true);
5362
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005363 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
5364 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005365
5366 // Set a value that's significantly larger than the default consumption timeout. If the
5367 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
5368 mFakePolicy->setInterceptKeyTimeout(600ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005369 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005370 // Window should receive key event immediately when same key up.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005371 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005372}
5373
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005374/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005375 * Two windows. First is a regular window. Second does not overlap with the first, and has
5376 * WATCH_OUTSIDE_TOUCH.
5377 * Both windows are owned by the same UID.
5378 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
5379 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
5380 */
5381TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
5382 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005383 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5384 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005385 window->setFrame(Rect{0, 0, 100, 100});
5386
5387 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005388 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005389 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005390 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5391 outsideWindow->setWatchOutsideTouch(true);
5392 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005393 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005394
5395 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005396 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005397 AINPUT_SOURCE_TOUCHSCREEN,
5398 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005399 window->consumeMotionDown();
5400 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
5401 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
5402 outsideWindow->consumeMotionEvent(
5403 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005404
5405 // Ensure outsideWindow doesn't get any more events for the gesture.
5406 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005407 ui::LogicalDisplayId::DEFAULT, {PointF{51, 51}}));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005408 window->consumeMotionMove();
5409 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005410}
5411
5412/**
Linnan Liccf6ce32024-04-11 20:32:13 +08005413 * Three windows:
5414 * - Left window
5415 * - Right window
5416 * - Outside window(watch for ACTION_OUTSIDE events)
5417 * The windows "left" and "outside" share the same owner, the window "right" has a different owner,
5418 * In order to allow the outside window can receive the ACTION_OUTSIDE events, the outside window is
5419 * positioned above the "left" and "right" windows, and it doesn't overlap with them.
5420 *
5421 * First, device A report a down event landed in the right window, the outside window can receive
5422 * an ACTION_OUTSIDE event that with zeroed coordinates, the device B report a down event landed
5423 * in the left window, the outside window can receive an ACTION_OUTSIDE event the with valid
5424 * coordinates, after these, device A and device B continue report MOVE event, the right and left
5425 * window can receive it, but outside window event can't receive it.
5426 */
5427TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinatesWhenMultiDevice) {
5428 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5429 sp<FakeWindowHandle> leftWindow =
5430 sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005431 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005432 leftWindow->setFrame(Rect{0, 0, 100, 100});
5433 leftWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5434
5435 sp<FakeWindowHandle> outsideWindow =
5436 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005437 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005438 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5439 outsideWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5440 outsideWindow->setWatchOutsideTouch(true);
5441
5442 std::shared_ptr<FakeApplicationHandle> anotherApplication =
5443 std::make_shared<FakeApplicationHandle>();
5444 sp<FakeWindowHandle> rightWindow =
5445 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Right Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005446 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005447 rightWindow->setFrame(Rect{100, 0, 200, 100});
5448 rightWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
5449
5450 // OutsideWindow must be above left window and right window to receive ACTION_OUTSIDE events
5451 // when left window or right window is tapped
5452 mDispatcher->onWindowInfosChanged(
5453 {{*outsideWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()},
5454 {},
5455 0,
5456 0});
5457
5458 const DeviceId deviceA = 9;
5459 const DeviceId deviceB = 3;
5460
5461 // Tap on right window use device A
5462 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5463 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5464 .deviceId(deviceA)
5465 .build());
5466 leftWindow->assertNoEvents();
5467 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5468 // Right window is belonged to another owner, so outsideWindow should receive ACTION_OUTSIDE
5469 // with zeroed coords.
5470 outsideWindow->consumeMotionEvent(
5471 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceA), WithCoords(0, 0)));
5472
5473 // Tap on left window use device B
5474 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5475 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5476 .deviceId(deviceB)
5477 .build());
5478 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5479 rightWindow->assertNoEvents();
5480 // Because new gesture down on the left window that has the same owner with outside Window, the
5481 // outside Window should receive the ACTION_OUTSIDE with coords.
5482 outsideWindow->consumeMotionEvent(
5483 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceB), WithCoords(-50, -50)));
5484
5485 // Ensure that windows that can only accept outside do not receive remaining gestures
5486 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5487 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
5488 .deviceId(deviceA)
5489 .build());
5490 leftWindow->assertNoEvents();
5491 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA)));
5492
5493 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5494 .pointer(PointerBuilder(0, ToolType::FINGER).x(51).y(51))
5495 .deviceId(deviceB)
5496 .build());
5497 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
5498 rightWindow->assertNoEvents();
5499 outsideWindow->assertNoEvents();
5500}
5501
5502/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005503 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
5504 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
5505 * ACTION_OUTSIDE event is sent per gesture.
5506 */
5507TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
5508 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
5509 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005510 sp<FakeWindowHandle> window =
5511 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5512 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005513 window->setWatchOutsideTouch(true);
5514 window->setFrame(Rect{0, 0, 100, 100});
5515 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005516 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005517 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005518 secondWindow->setFrame(Rect{100, 100, 200, 200});
5519 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005520 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005521 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005522 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005523 mDispatcher->onWindowInfosChanged(
5524 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005525
5526 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005527 mDispatcher->notifyMotion(
5528 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5529 ui::LogicalDisplayId::DEFAULT, {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005530 window->assertNoEvents();
5531 secondWindow->assertNoEvents();
5532
5533 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
5534 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005535 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005536 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005537 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005538 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
5539 window->consumeMotionEvent(
5540 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005541 secondWindow->consumeMotionDown();
5542 thirdWindow->assertNoEvents();
5543
5544 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
5545 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005546 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005547 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5548 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005549 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005550 window->assertNoEvents();
5551 secondWindow->consumeMotionMove();
5552 thirdWindow->consumeMotionDown();
5553}
5554
Prabir Pradhan814fe082022-07-22 20:22:18 +00005555TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
5556 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005557 sp<FakeWindowHandle> window =
5558 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5559 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005560 window->setFocusable(true);
5561
Patrick Williamsd828f302023-04-28 17:52:08 -05005562 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005563 setFocusedWindow(window);
5564
5565 window->consumeFocusEvent(true);
5566
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005567 const NotifyKeyArgs keyDown =
5568 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
5569 const NotifyKeyArgs keyUp =
5570 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005571 mDispatcher->notifyKey(keyDown);
5572 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005573
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005574 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5575 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005576
5577 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05005578 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005579
5580 window->consumeFocusEvent(false);
5581
Prabir Pradhan678438e2023-04-13 19:32:51 +00005582 mDispatcher->notifyKey(keyDown);
5583 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005584 window->assertNoEvents();
5585}
5586
Arthur Hung96483742022-11-15 03:30:48 +00005587TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
5588 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005589 sp<FakeWindowHandle> window =
5590 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5591 ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005592 // Ensure window is non-split and have some transform.
5593 window->setPreventSplitting(true);
5594 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05005595 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00005596
5597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005598 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5599 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung96483742022-11-15 03:30:48 +00005600 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005601 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005602
5603 const MotionEvent secondFingerDownEvent =
5604 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005605 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung96483742022-11-15 03:30:48 +00005606 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005607 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5608 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00005609 .build();
5610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005611 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00005612 InputEventInjectionSync::WAIT_FOR_RESULT))
5613 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5614
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005615 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
5616 ASSERT_NE(nullptr, event);
5617 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
5618 EXPECT_EQ(70, event->getX(0)); // 50 + 20
5619 EXPECT_EQ(90, event->getY(0)); // 50 + 40
5620 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
5621 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00005622}
5623
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005624/**
5625 * Two windows: a splittable and a non-splittable.
5626 * The non-splittable window shouldn't receive any "incomplete" gestures.
5627 * Send the first pointer to the splittable window, and then touch the non-splittable window.
5628 * The second pointer should be dropped because the initial window is splittable, so it won't get
5629 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
5630 * "incomplete" gestures.
5631 */
5632TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
5633 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5634 sp<FakeWindowHandle> leftWindow =
5635 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005636 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005637 leftWindow->setPreventSplitting(false);
5638 leftWindow->setFrame(Rect(0, 0, 100, 100));
5639 sp<FakeWindowHandle> rightWindow =
5640 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005641 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005642 rightWindow->setPreventSplitting(true);
5643 rightWindow->setFrame(Rect(100, 100, 200, 200));
5644 mDispatcher->onWindowInfosChanged(
5645 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5646
5647 // Touch down on left, splittable window
5648 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5649 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5650 .build());
5651 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5652
5653 mDispatcher->notifyMotion(
5654 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5655 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5656 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
5657 .build());
5658 leftWindow->assertNoEvents();
5659 rightWindow->assertNoEvents();
5660}
5661
Harry Cuttsb166c002023-05-09 13:06:05 +00005662TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
5663 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005664 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5665 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005666 window->setFrame(Rect(0, 0, 400, 400));
5667 sp<FakeWindowHandle> trustedOverlay =
5668 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005669 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005670 trustedOverlay->setSpy(true);
5671 trustedOverlay->setTrustedOverlay(true);
5672
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005673 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005674
5675 // Start a three-finger touchpad swipe
5676 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5677 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5678 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5679 .build());
5680 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5681 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5682 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5683 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5684 .build());
5685 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5686 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5687 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5688 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5689 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5690 .build());
5691
5692 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5693 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5694 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
5695
5696 // Move the swipe a bit
5697 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5698 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5699 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5700 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5701 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5702 .build());
5703
5704 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5705
5706 // End the swipe
5707 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5708 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5709 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5710 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5711 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5712 .build());
5713 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5714 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5715 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5716 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5717 .build());
5718 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5719 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5720 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5721 .build());
5722
5723 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
5724 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5725 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
5726
5727 window->assertNoEvents();
5728}
5729
5730TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
5731 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005732 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5733 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005734 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005735 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005736
5737 // Start a three-finger touchpad swipe
5738 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5739 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5740 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5741 .build());
5742 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5743 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5744 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5745 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5746 .build());
5747 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5748 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5749 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5750 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5751 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5752 .build());
5753
5754 // Move the swipe a bit
5755 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5756 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5757 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5758 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5759 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5760 .build());
5761
5762 // End the swipe
5763 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5764 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5765 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5766 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5767 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5768 .build());
5769 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5770 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5771 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5772 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5773 .build());
5774 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5775 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5776 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5777 .build());
5778
5779 window->assertNoEvents();
5780}
5781
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005782/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005783 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
5784 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005785 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005786 */
5787TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
5788 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005789 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5790 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005791 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005792 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005793
5794 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
5795 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5796 .downTime(baseTime + 10)
5797 .eventTime(baseTime + 10)
5798 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5799 .build());
5800
5801 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5802
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005803 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005804 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005805
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005806 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005807
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005808 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5809 .downTime(baseTime + 10)
5810 .eventTime(baseTime + 30)
5811 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5812 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5813 .build());
5814
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005815 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5816
5817 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005818 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5819 .downTime(baseTime + 10)
5820 .eventTime(baseTime + 40)
5821 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5822 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5823 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005824
5825 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5826
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005827 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5828 .downTime(baseTime + 10)
5829 .eventTime(baseTime + 50)
5830 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5831 .build());
5832
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005833 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
5834
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005835 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5836 .downTime(baseTime + 60)
5837 .eventTime(baseTime + 60)
5838 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
5839 .build());
5840
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005841 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005842}
5843
5844/**
Hu Guo771a7692023-09-17 20:51:08 +08005845 * When there are multiple screens, such as screen projection to TV or screen recording, if the
5846 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
5847 * its coordinates should be converted by the transform of the windows of target screen.
5848 */
5849TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
5850 // This case will create a window and a spy window on the default display and mirror
5851 // window on the second display. cancel event is sent through spy window pilferPointers
5852 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5853
5854 sp<FakeWindowHandle> spyWindowDefaultDisplay =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005855 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
5856 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005857 spyWindowDefaultDisplay->setTrustedOverlay(true);
5858 spyWindowDefaultDisplay->setSpy(true);
5859
5860 sp<FakeWindowHandle> windowDefaultDisplay =
5861 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005862 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005863 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
5864
5865 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
5866 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
5867
5868 // Add the windows to the dispatcher
5869 mDispatcher->onWindowInfosChanged(
5870 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
5871 *windowSecondDisplay->getInfo()},
5872 {},
5873 0,
5874 0});
5875
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005876 // Send down to ui::LogicalDisplayId::DEFAULT
Hu Guo771a7692023-09-17 20:51:08 +08005877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005878 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5879 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Hu Guo771a7692023-09-17 20:51:08 +08005880 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5881
5882 spyWindowDefaultDisplay->consumeMotionDown();
5883 windowDefaultDisplay->consumeMotionDown();
5884
5885 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
5886
5887 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005888 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
5889 ASSERT_NE(nullptr, event);
5890 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08005891
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005892 // The cancel event is sent to windowDefaultDisplay of the ui::LogicalDisplayId::DEFAULT
5893 // display, so the coordinates of the cancel are converted by windowDefaultDisplay's transform,
5894 // the x and y coordinates are both 100, otherwise if the cancel event is sent to
5895 // windowSecondDisplay of SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005896 EXPECT_EQ(100, event->getX(0));
5897 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08005898}
5899
5900/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005901 * Ensure the correct coordinate spaces are used by InputDispatcher.
5902 *
5903 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5904 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5905 * space.
5906 */
5907class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5908public:
5909 void SetUp() override {
5910 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005911 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005912 }
5913
Linnan Li13bf76a2024-05-05 19:18:02 +08005914 void addDisplayInfo(ui::LogicalDisplayId displayId, const ui::Transform& transform) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005915 gui::DisplayInfo info;
5916 info.displayId = displayId;
5917 info.transform = transform;
5918 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005919 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005920 }
5921
5922 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5923 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005924 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005925 }
5926
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005927 void removeAllWindowsAndDisplays() {
5928 mDisplayInfos.clear();
5929 mWindowInfos.clear();
5930 }
5931
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005932 // Set up a test scenario where the display has a scaled projection and there are two windows
5933 // on the display.
5934 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5935 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5936 // respectively.
5937 ui::Transform displayTransform;
5938 displayTransform.set(2, 0, 0, 4);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005939 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005940
5941 std::shared_ptr<FakeApplicationHandle> application =
5942 std::make_shared<FakeApplicationHandle>();
5943
5944 // Add two windows to the display. Their frames are represented in the display space.
5945 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005946 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005947 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005948 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5949 addWindow(firstWindow);
5950
5951 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005952 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005953 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005954 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5955 addWindow(secondWindow);
5956 return {std::move(firstWindow), std::move(secondWindow)};
5957 }
5958
5959private:
5960 std::vector<gui::DisplayInfo> mDisplayInfos;
5961 std::vector<gui::WindowInfo> mWindowInfos;
5962};
5963
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005964TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005965 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5966 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005967 // selected so that if the hit test was performed with the point and the bounds being in
5968 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005969 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005970 AINPUT_SOURCE_TOUCHSCREEN,
5971 ui::LogicalDisplayId::DEFAULT, {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005972
5973 firstWindow->consumeMotionDown();
5974 secondWindow->assertNoEvents();
5975}
5976
5977// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5978// the event should be treated as being in the logical display space.
5979TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5980 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5981 // Send down to the first window. The point is represented in the logical display space. The
5982 // point is selected so that if the hit test was done in logical display space, then it would
5983 // end up in the incorrect window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005984 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005985 PointF{75 * 2, 55 * 4});
5986
5987 firstWindow->consumeMotionDown();
5988 secondWindow->assertNoEvents();
5989}
5990
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005991// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5992// event should be treated as being in the logical display space.
5993TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5994 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5995
5996 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5997 ui::Transform injectedEventTransform;
5998 injectedEventTransform.set(matrix);
5999 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
6000 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
6001
6002 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006003 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006004 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006005 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006006 .x(untransformedPoint.x)
6007 .y(untransformedPoint.y))
6008 .build();
6009 event.transform(matrix);
6010
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006011 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006012 InputEventInjectionSync::WAIT_FOR_RESULT);
6013
6014 firstWindow->consumeMotionDown();
6015 secondWindow->assertNoEvents();
6016}
6017
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006018TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
6019 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6020
6021 // Send down to the second window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006022 mDispatcher->notifyMotion(
6023 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6024 ui::LogicalDisplayId::DEFAULT, {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006025
6026 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006027 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
6028 ASSERT_NE(nullptr, event);
6029 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006030
6031 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006032 EXPECT_EQ(300, event->getRawX(0));
6033 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006034
6035 // Ensure that the x and y values are in the window's coordinate space.
6036 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
6037 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006038 EXPECT_EQ(100, event->getX(0));
6039 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006040}
6041
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006042TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
6043 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6044 // The monitor will always receive events in the logical display's coordinate space, because
6045 // it does not have a window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006046 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ui::LogicalDisplayId::DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006047
6048 // Send down to the first window.
6049 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006050 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006051 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6052 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6053
6054 // Second pointer goes down on second window.
6055 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006056 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006057 {PointF{50, 100}, PointF{150, 220}}));
6058 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
6059 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
6060 {1, PointF{300, 880}}};
6061 monitor.consumeMotionEvent(
6062 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
6063
6064 mDispatcher->cancelCurrentTouch();
6065
6066 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
6067 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
6068 monitor.consumeMotionEvent(
6069 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
6070}
6071
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006072TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
6073 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6074
6075 // Send down to the first window.
6076 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006077 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006078 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6079
6080 // The pointer is transferred to the second window, and the second window receives it in the
6081 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006082 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006083 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
6084 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
6085}
6086
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006087TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
6088 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6089
6090 // Send hover move to the second window, and ensure it shows up as hover enter.
6091 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006092 ui::LogicalDisplayId::DEFAULT,
6093 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006094 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6095 WithCoords(100, 80), WithRawCoords(300, 880)));
6096
6097 // Touch down at the same location and ensure a hover exit is synthesized.
6098 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006099 ui::LogicalDisplayId::DEFAULT,
6100 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006101 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6102 WithRawCoords(300, 880)));
6103 secondWindow->consumeMotionEvent(
6104 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
6105 secondWindow->assertNoEvents();
6106 firstWindow->assertNoEvents();
6107}
6108
Prabir Pradhan453ae732023-10-13 14:30:14 +00006109// Same as above, but while the window is being mirrored.
6110TEST_F(InputDispatcherDisplayProjectionTest,
6111 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
6112 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6113
6114 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6115 ui::Transform secondDisplayTransform;
6116 secondDisplayTransform.set(matrix);
6117 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
6118
6119 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
6120 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
6121 addWindow(secondWindowClone);
6122
6123 // Send hover move to the second window, and ensure it shows up as hover enter.
6124 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006125 ui::LogicalDisplayId::DEFAULT,
6126 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00006127 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6128 WithCoords(100, 80), WithRawCoords(300, 880)));
6129
6130 // Touch down at the same location and ensure a hover exit is synthesized for the correct
6131 // display.
6132 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006133 ui::LogicalDisplayId::DEFAULT,
6134 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00006135 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6136 WithRawCoords(300, 880)));
6137 secondWindow->consumeMotionEvent(
6138 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
6139 secondWindow->assertNoEvents();
6140 firstWindow->assertNoEvents();
6141}
6142
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006143TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
6144 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6145
6146 // Send hover enter to second window
6147 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006148 ui::LogicalDisplayId::DEFAULT,
6149 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006150 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6151 WithCoords(100, 80), WithRawCoords(300, 880)));
6152
6153 mDispatcher->cancelCurrentTouch();
6154
6155 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6156 WithRawCoords(300, 880)));
6157 secondWindow->assertNoEvents();
6158 firstWindow->assertNoEvents();
6159}
6160
Prabir Pradhan453ae732023-10-13 14:30:14 +00006161// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00006162TEST_F(InputDispatcherDisplayProjectionTest,
6163 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
6164 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6165
6166 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6167 ui::Transform secondDisplayTransform;
6168 secondDisplayTransform.set(matrix);
6169 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
6170
6171 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
6172 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
6173 addWindow(secondWindowClone);
6174
6175 // Send hover enter to second window
6176 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006177 ui::LogicalDisplayId::DEFAULT,
6178 {PointF{150, 220}}));
Prabir Pradhan16463382023-10-12 23:03:19 +00006179 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6180 WithCoords(100, 80), WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006181 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00006182
6183 mDispatcher->cancelCurrentTouch();
6184
6185 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
6186 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6187 WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006188 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00006189 secondWindow->assertNoEvents();
6190 firstWindow->assertNoEvents();
6191}
6192
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006193/** Ensure consistent behavior of InputDispatcher in all orientations. */
6194class InputDispatcherDisplayOrientationFixture
6195 : public InputDispatcherDisplayProjectionTest,
6196 public ::testing::WithParamInterface<ui::Rotation> {};
6197
6198// This test verifies the touchable region of a window for all rotations of the display by tapping
6199// in different locations on the display, specifically points close to the four corners of a
6200// window.
6201TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
6202 constexpr static int32_t displayWidth = 400;
6203 constexpr static int32_t displayHeight = 800;
6204
6205 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6206
6207 const auto rotation = GetParam();
6208
6209 // Set up the display with the specified rotation.
6210 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6211 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6212 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6213 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6214 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006215 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006216
6217 // Create a window with its bounds determined in the logical display.
6218 const Rect frameInLogicalDisplay(100, 100, 200, 300);
6219 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006220 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6221 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006222 window->setFrame(frameInDisplay, displayTransform);
6223 addWindow(window);
6224
6225 // The following points in logical display space should be inside the window.
6226 static const std::array<vec2, 4> insidePoints{
6227 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6228 for (const auto pointInsideWindow : insidePoints) {
6229 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
6230 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006231 mDispatcher->notifyMotion(
6232 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6233 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006234 window->consumeMotionDown();
6235
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006236 mDispatcher->notifyMotion(
6237 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6238 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006239 window->consumeMotionUp();
6240 }
6241
6242 // The following points in logical display space should be outside the window.
6243 static const std::array<vec2, 5> outsidePoints{
6244 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6245 for (const auto pointOutsideWindow : outsidePoints) {
6246 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
6247 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006248 mDispatcher->notifyMotion(
6249 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6250 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006251
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006252 mDispatcher->notifyMotion(
6253 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6254 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006255 }
6256 window->assertNoEvents();
6257}
6258
Linnan Li5e5645e2024-03-05 14:43:05 +00006259// This test verifies the occlusion detection for all rotations of the display by tapping
6260// in different locations on the display, specifically points close to the four corners of a
6261// window.
6262TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) {
6263 constexpr static int32_t displayWidth = 400;
6264 constexpr static int32_t displayHeight = 800;
6265
6266 std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication =
6267 std::make_shared<FakeApplicationHandle>();
6268 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6269
6270 const auto rotation = GetParam();
6271
6272 // Set up the display with the specified rotation.
6273 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6274 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6275 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6276 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6277 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006278 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Linnan Li5e5645e2024-03-05 14:43:05 +00006279
6280 // Create a window that not trusted.
6281 const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
6282
6283 const Rect untrustedWindowFrameInDisplay =
6284 displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay);
6285
6286 sp<FakeWindowHandle> untrustedWindow =
6287 sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006288 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006289 untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
6290 untrustedWindow->setTrustedOverlay(false);
6291 untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
6292 untrustedWindow->setTouchable(false);
6293 untrustedWindow->setAlpha(1.0f);
6294 untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
6295 addWindow(untrustedWindow);
6296
6297 // Create a simple app window below the untrusted window.
6298 const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600);
6299 const Rect simpleAppWindowFrameInDisplay =
6300 displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay);
6301
6302 sp<FakeWindowHandle> simpleAppWindow =
6303 sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006304 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006305 simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
6306 simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
6307 addWindow(simpleAppWindow);
6308
6309 // The following points in logical display space should be inside the untrusted window, so
6310 // the simple window could not receive events that coordinate is these point.
6311 static const std::array<vec2, 4> untrustedPoints{
6312 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6313
6314 for (const auto untrustedPoint : untrustedPoints) {
6315 const vec2 p = displayTransform.inverse().transform(untrustedPoint);
6316 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006317 mDispatcher->notifyMotion(
6318 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6319 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6320 mDispatcher->notifyMotion(
6321 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6322 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Linnan Li5e5645e2024-03-05 14:43:05 +00006323 }
6324 untrustedWindow->assertNoEvents();
6325 simpleAppWindow->assertNoEvents();
6326 // The following points in logical display space should be outside the untrusted window, so
6327 // the simple window should receive events that coordinate is these point.
6328 static const std::array<vec2, 5> trustedPoints{
6329 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6330 for (const auto trustedPoint : trustedPoints) {
6331 const vec2 p = displayTransform.inverse().transform(trustedPoint);
6332 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006333 mDispatcher->notifyMotion(
6334 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6335 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6336 simpleAppWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006337 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006338 mDispatcher->notifyMotion(
6339 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6340 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6341 simpleAppWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006342 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6343 }
6344 untrustedWindow->assertNoEvents();
6345}
6346
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006347// Run the precision tests for all rotations.
6348INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
6349 InputDispatcherDisplayOrientationFixture,
6350 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6351 ui::ROTATION_270),
6352 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6353 return ftl::enum_string(testParamInfo.param);
6354 });
6355
Siarhei Vishniakou18050092021-09-01 13:32:49 -07006356using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
6357 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006358
6359class TransferTouchFixture : public InputDispatcherTest,
6360 public ::testing::WithParamInterface<TransferFunction> {};
6361
6362TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07006363 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006364
6365 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006366 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006367 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006368 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006369 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006370 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006371 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006372 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006373 sp<FakeWindowHandle> wallpaper =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006374 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
6375 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006376 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006377 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006378 mDispatcher->onWindowInfosChanged(
6379 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00006380 setFocusedWindow(firstWindow);
6381 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006382
6383 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006384 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006385 AINPUT_SOURCE_TOUCHSCREEN,
6386 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006387
Svet Ganov5d3bc372020-01-26 23:11:07 -08006388 // Only the first window should get the down event
6389 firstWindow->consumeMotionDown();
6390 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006391 wallpaper->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006392 // Dispatcher reports pointer down outside focus for the wallpaper
6393 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006394
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006395 // Transfer touch to the second window
6396 TransferFunction f = GetParam();
6397 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6398 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006399 // The first window gets cancel and the second gets down
6400 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006401 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6402 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6403 wallpaper->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006404 // There should not be any changes to the focused window when transferring touch
6405 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006406
6407 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006408 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006409 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00006410 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08006411 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006412 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6413 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006414 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006415}
6416
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006417/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00006418 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
6419 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
6420 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006421 * natural to the user.
6422 * In this test, we are sending a pointer to both spy window and first window. We then try to
6423 * transfer touch to the second window. The dispatcher should identify the first window as the
6424 * one that should lose the gesture, and therefore the action should be to move the gesture from
6425 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006426 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
6427 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006428 */
6429TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
6430 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6431
6432 // Create a couple of windows + a spy window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006433 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6434 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006435 spyWindow->setTrustedOverlay(true);
6436 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006437 sp<FakeWindowHandle> firstWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "First",
6438 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006439 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006440 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
6441 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006442
6443 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006444 mDispatcher->onWindowInfosChanged(
6445 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006446
6447 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006448 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006449 AINPUT_SOURCE_TOUCHSCREEN,
6450 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006451 // Only the first window and spy should get the down event
6452 spyWindow->consumeMotionDown();
6453 firstWindow->consumeMotionDown();
6454
6455 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00006456 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006457 TransferFunction f = GetParam();
6458 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6459 ASSERT_TRUE(success);
6460 // The first window gets cancel and the second gets down
6461 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006462 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6463 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006464
6465 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006466 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006467 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006468 // The first window gets no events and the second+spy get up
6469 firstWindow->assertNoEvents();
6470 spyWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006471 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6472 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006473}
6474
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006475TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006476 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006477
6478 PointF touchPoint = {10, 10};
6479
6480 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006481 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006482 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006483 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006484 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006485 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006486 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006487 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006488 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006489
6490 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006491 mDispatcher->onWindowInfosChanged(
6492 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006493
6494 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006495 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006496 AINPUT_SOURCE_TOUCHSCREEN,
6497 ui::LogicalDisplayId::DEFAULT, {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006498 // Only the first window should get the down event
6499 firstWindow->consumeMotionDown();
6500 secondWindow->assertNoEvents();
6501
6502 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006503 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006504 ui::LogicalDisplayId::DEFAULT,
6505 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006506 // Only the first window should get the pointer down event
6507 firstWindow->consumeMotionPointerDown(1);
6508 secondWindow->assertNoEvents();
6509
6510 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006511 TransferFunction f = GetParam();
6512 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6513 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006514 // The first window gets cancel and the second gets down and pointer down
6515 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006516 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6517 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6518 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006519 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006520
6521 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006522 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006523 ui::LogicalDisplayId::DEFAULT,
6524 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006525 // The first window gets nothing and the second gets pointer up
6526 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00006527 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
6528 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
6529 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
6530 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006531
6532 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006533 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006534 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006535 // The first window gets nothing and the second gets up
6536 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006537 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6538 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006539}
6540
Arthur Hungc539dbb2022-12-08 07:45:36 +00006541TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
6542 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6543
6544 // Create a couple of windows
6545 sp<FakeWindowHandle> firstWindow =
6546 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006547 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006548 firstWindow->setDupTouchToWallpaper(true);
6549 sp<FakeWindowHandle> secondWindow =
6550 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006551 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006552 secondWindow->setDupTouchToWallpaper(true);
6553
6554 sp<FakeWindowHandle> wallpaper1 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006555 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1",
6556 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006557 wallpaper1->setIsWallpaper(true);
6558
6559 sp<FakeWindowHandle> wallpaper2 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006560 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2",
6561 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006562 wallpaper2->setIsWallpaper(true);
6563 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006564 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
6565 *secondWindow->getInfo(), *wallpaper2->getInfo()},
6566 {},
6567 0,
6568 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00006569
6570 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006571 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006572 AINPUT_SOURCE_TOUCHSCREEN,
6573 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006574
6575 // Only the first window should get the down event
6576 firstWindow->consumeMotionDown();
6577 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006578 wallpaper1->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006579 wallpaper2->assertNoEvents();
6580
6581 // Transfer touch focus to the second window
6582 TransferFunction f = GetParam();
6583 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6584 ASSERT_TRUE(success);
6585
6586 // The first window gets cancel and the second gets down
6587 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006588 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6589 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6590 wallpaper1->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
6591 wallpaper2->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006592 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006593
6594 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006595 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006596 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006597 // The first window gets no events and the second gets up
6598 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006599 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6600 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006601 wallpaper1->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006602 wallpaper2->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006603 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006604}
6605
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006606// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00006607// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006608// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006609INSTANTIATE_TEST_SUITE_P(
6610 InputDispatcherTransferFunctionTests, TransferTouchFixture,
6611 ::testing::Values(
6612 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
6613 sp<IBinder> destChannelToken) {
6614 return dispatcher->transferTouchOnDisplay(destChannelToken,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006615 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006616 },
6617 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
6618 sp<IBinder> to) {
6619 return dispatcher->transferTouchGesture(from, to,
6620 /*isDragAndDrop=*/false);
6621 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006622
Prabir Pradhan367f3432024-02-13 23:05:58 +00006623TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006624 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006625
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006626 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006627 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006628 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006629 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006630
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006631 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006632 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006633 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006634 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006635
6636 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006637 mDispatcher->onWindowInfosChanged(
6638 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006639
6640 PointF pointInFirst = {300, 200};
6641 PointF pointInSecond = {300, 600};
6642
6643 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006644 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006645 AINPUT_SOURCE_TOUCHSCREEN,
6646 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006647 // Only the first window should get the down event
6648 firstWindow->consumeMotionDown();
6649 secondWindow->assertNoEvents();
6650
6651 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006652 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006653 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006654 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006655 // The first window gets a move and the second a down
6656 firstWindow->consumeMotionMove();
6657 secondWindow->consumeMotionDown();
6658
Prabir Pradhan367f3432024-02-13 23:05:58 +00006659 // Transfer touch to the second window
6660 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006661 // The first window gets cancel and the new gets pointer down (it already saw down)
6662 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006663 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006664 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006665
6666 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006667 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006668 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006669 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006670 // The first window gets nothing and the second gets pointer up
6671 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00006672 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
6673 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
6674 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
6675 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006676
6677 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006678 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006679 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006680 // The first window gets nothing and the second gets up
6681 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006682 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6683 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006684}
6685
Prabir Pradhan367f3432024-02-13 23:05:58 +00006686// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
6687// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
6688// receiving touch is not supported, so the touch should continue on those windows and the
6689// transferred-to window should get nothing.
6690TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006691 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6692
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006693 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006694 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006695 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006696 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006697
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006698 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006699 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006700 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006701 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006702
6703 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006704 mDispatcher->onWindowInfosChanged(
6705 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006706
6707 PointF pointInFirst = {300, 200};
6708 PointF pointInSecond = {300, 600};
6709
6710 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006711 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006712 AINPUT_SOURCE_TOUCHSCREEN,
6713 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006714 // Only the first window should get the down event
6715 firstWindow->consumeMotionDown();
6716 secondWindow->assertNoEvents();
6717
6718 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006719 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006720 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006721 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006722 // The first window gets a move and the second a down
6723 firstWindow->consumeMotionMove();
6724 secondWindow->consumeMotionDown();
6725
6726 // Transfer touch focus to the second window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006727 const bool transferred = mDispatcher->transferTouchOnDisplay(secondWindow->getToken(),
6728 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006729 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006730 ASSERT_FALSE(transferred);
6731 firstWindow->assertNoEvents();
6732 secondWindow->assertNoEvents();
6733
6734 // The rest of the dispatch should proceed as normal
6735 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006736 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006737 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006738 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006739 // The first window gets MOVE and the second gets pointer up
6740 firstWindow->consumeMotionMove();
6741 secondWindow->consumeMotionUp();
6742
6743 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006744 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006745 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006746 // The first window gets nothing and the second gets up
6747 firstWindow->consumeMotionUp();
6748 secondWindow->assertNoEvents();
6749}
6750
Arthur Hungabbb9d82021-09-01 14:52:30 +00006751// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00006752// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00006753// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006754TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006755 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6756 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006757 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6758 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006759 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006760 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006761 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6762 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006763 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006764
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006765 sp<FakeWindowHandle> mirrorWindowInPrimary =
6766 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006767 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006768
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006769 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006770 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006771
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006772 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006773 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006774
6775 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006776 mDispatcher->onWindowInfosChanged(
6777 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6778 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6779 *secondWindowInPrimary->getInfo()},
6780 {},
6781 0,
6782 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006783
6784 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006785 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6786 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006787 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6788
6789 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006790 firstWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006791
Prabir Pradhan367f3432024-02-13 23:05:58 +00006792 // Transfer touch
6793 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
6794 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006795 // The first window gets cancel.
6796 firstWindowInPrimary->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006797 secondWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006798 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006799
6800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006801 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006802 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006803 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6804 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006805 secondWindowInPrimary->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006806 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006807
6808 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006809 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006810 {150, 50}))
6811 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6812 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006813 secondWindowInPrimary->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6814 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006815}
6816
Prabir Pradhan367f3432024-02-13 23:05:58 +00006817// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
6818// 'transferTouchOnDisplay' api.
6819TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006820 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6821 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006822 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6823 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006824 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006825 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006826 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6827 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006828 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006829
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006830 sp<FakeWindowHandle> mirrorWindowInPrimary =
6831 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006832 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006833
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006834 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006835 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006836
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006837 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006838 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006839
6840 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006841 mDispatcher->onWindowInfosChanged(
6842 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6843 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6844 *secondWindowInPrimary->getInfo()},
6845 {},
6846 0,
6847 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006848
6849 // Touch on second display.
6850 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006851 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6852 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006853 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6854
6855 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006856 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006857
6858 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00006859 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
6860 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006861
6862 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006863 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006864 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
6865 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006866
6867 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006868 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006869 SECOND_DISPLAY_ID, {150, 50}))
6870 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006871 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006872 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
6873 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006874
6875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006876 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006877 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006878 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006879 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006880}
6881
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006882TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006883 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006884 sp<FakeWindowHandle> window =
6885 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6886 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006887
Vishnu Nair47074b82020-08-14 11:54:47 -07006888 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006889 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006890 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006891
6892 window->consumeFocusEvent(true);
6893
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006894 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006895
6896 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006897 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006898
6899 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006900 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006901 mFakePolicy->assertUserActivityPoked();
6902}
6903
6904TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
6905 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006906 sp<FakeWindowHandle> window =
6907 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6908 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006909
6910 window->setDisableUserActivity(true);
6911 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006912 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006913 setFocusedWindow(window);
6914
6915 window->consumeFocusEvent(true);
6916
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006917 mDispatcher->notifyKey(
6918 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006919
6920 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006921 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006922
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006923 // Should have not poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006924 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006925 mFakePolicy->assertUserActivityNotPoked();
6926}
6927
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006928TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyConsumedKey) {
Josep del Riob3981622023-04-18 15:49:45 +00006929 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006930 sp<FakeWindowHandle> window =
6931 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6932 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006933
6934 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006935 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006936 setFocusedWindow(window);
6937
6938 window->consumeFocusEvent(true);
6939
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006940 mFakePolicy->setConsumeKeyBeforeDispatching(true);
6941
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006942 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006943 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006944 mDispatcher->waitForIdle();
6945
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006946 // Key is not passed down
Josep del Riob3981622023-04-18 15:49:45 +00006947 window->assertNoEvents();
6948
6949 // Should have poked user activity
6950 mFakePolicy->assertUserActivityPoked();
6951}
6952
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006953TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserActivity) {
Josep del Riob3981622023-04-18 15:49:45 +00006954 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006955 sp<FakeWindowHandle> window =
6956 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6957 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006958
6959 window->setDisableUserActivity(true);
6960 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006961 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006962 setFocusedWindow(window);
6963
6964 window->consumeFocusEvent(true);
6965
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006966 mFakePolicy->setConsumeKeyBeforeDispatching(true);
6967
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006968 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006969 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006970 mDispatcher->waitForIdle();
6971
6972 // System key is not passed down
6973 window->assertNoEvents();
6974
6975 // Should have poked user activity
6976 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006977}
6978
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006979class DisableUserActivityInputDispatcherTest : public InputDispatcherTest,
6980 public ::testing::WithParamInterface<bool> {};
6981
6982TEST_P(DisableUserActivityInputDispatcherTest, NotPassedToUserUserActivity) {
6983 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6984 sp<FakeWindowHandle> window =
6985 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6986 ui::LogicalDisplayId::DEFAULT);
6987
6988 window->setDisableUserActivity(GetParam());
6989
6990 window->setFocusable(true);
6991 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6992 setFocusedWindow(window);
6993
6994 window->consumeFocusEvent(true);
6995
6996 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
6997 .keyCode(AKEYCODE_A)
6998 .policyFlags(0)
6999 .build());
7000 mDispatcher->waitForIdle();
7001
7002 // Key is not passed down
7003 window->assertNoEvents();
7004
7005 // Should not have poked user activity
7006 mFakePolicy->assertUserActivityNotPoked();
7007}
7008
7009INSTANTIATE_TEST_CASE_P(DisableUserActivity, DisableUserActivityInputDispatcherTest,
7010 ::testing::Bool());
7011
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007012TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
7013 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007014 sp<FakeWindowHandle> window =
7015 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7016 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007017
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007018 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007019
7020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007021 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007022 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007023 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7024
7025 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007026 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007027
7028 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00007029 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007030 mFakePolicy->assertUserActivityPoked();
7031}
7032
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007033TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007034 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007035 sp<FakeWindowHandle> window =
7036 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7037 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007038
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007039 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007040
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007041 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007042 mDispatcher->waitForIdle();
7043
7044 window->assertNoEvents();
7045}
7046
7047// If a window is touchable, but does not have focus, it should receive motion events, but not keys
7048TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07007049 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007050 sp<FakeWindowHandle> window =
7051 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7052 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007053
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007054 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007055
7056 // Send key
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007057 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007058 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00007059 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007060 AINPUT_SOURCE_TOUCHSCREEN,
7061 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007062
7063 // Window should receive only the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007064 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007065 window->assertNoEvents(); // Key event or focus event will not be received
7066}
7067
arthurhungea3f4fc2020-12-21 23:18:53 +08007068TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
7069 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7070
arthurhungea3f4fc2020-12-21 23:18:53 +08007071 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007072 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007073 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08007074 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08007075
arthurhungea3f4fc2020-12-21 23:18:53 +08007076 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007077 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007078 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08007079 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08007080
7081 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007082 mDispatcher->onWindowInfosChanged(
7083 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08007084
7085 PointF pointInFirst = {300, 200};
7086 PointF pointInSecond = {300, 600};
7087
7088 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007089 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007090 AINPUT_SOURCE_TOUCHSCREEN,
7091 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08007092 // Only the first window should get the down event
7093 firstWindow->consumeMotionDown();
7094 secondWindow->assertNoEvents();
7095
7096 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007097 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007098 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007099 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08007100 // The first window gets a move and the second a down
7101 firstWindow->consumeMotionMove();
7102 secondWindow->consumeMotionDown();
7103
7104 // Send pointer cancel to the second window
7105 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007106 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
7107 ui::LogicalDisplayId::DEFAULT, {pointInFirst, pointInSecond});
arthurhungea3f4fc2020-12-21 23:18:53 +08007108 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00007109 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08007110 // The first window gets move and the second gets cancel.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007111 firstWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
7112 secondWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
arthurhungea3f4fc2020-12-21 23:18:53 +08007113
7114 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007115 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007116 ui::LogicalDisplayId::DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08007117 // The first window gets up and the second gets nothing.
7118 firstWindow->consumeMotionUp();
7119 secondWindow->assertNoEvents();
7120}
7121
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007122TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
7123 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7124
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007125 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
7126 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007127 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007128 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
7129 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
7130 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
7131
Harry Cutts33476232023-01-30 19:57:29 +00007132 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007133 window->assertNoEvents();
7134 mDispatcher->waitForIdle();
7135}
7136
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007137using InputDispatcherMonitorTest = InputDispatcherTest;
7138
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007139/**
7140 * Two entities that receive touch: A window, and a global monitor.
7141 * The touch goes to the window, and then the window disappears.
7142 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
7143 * for the monitor, as well.
7144 * 1. foregroundWindow
7145 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
7146 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007147TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007148 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007149 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7150 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007151
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007152 FakeMonitorReceiver monitor =
7153 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007154
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007155 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007156 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007157 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7158 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007159 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7160
7161 // Both the foreground window and the global monitor should receive the touch down
7162 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007163 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007164
7165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007166 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007167 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007168 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7169
7170 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007171 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007172
7173 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007174 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007175 window->consumeMotionCancel();
7176 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
7177
7178 // If more events come in, there will be no more foreground window to send them to. This will
7179 // cause a cancel for the monitor, as well.
7180 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007181 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007182 ui::LogicalDisplayId::DEFAULT, {120, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007183 << "Injection should fail because the window was removed";
7184 window->assertNoEvents();
7185 // Global monitor now gets the cancel
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007186 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007187}
7188
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007189TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07007190 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007191 sp<FakeWindowHandle> window =
7192 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7193 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007194 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007195
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007196 FakeMonitorReceiver monitor =
7197 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007198
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007200 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7201 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007202 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007203 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7204 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007205}
7206
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007207TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007208 FakeMonitorReceiver monitor =
7209 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007210
Chris Yea209fde2020-07-22 13:54:51 -07007211 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007212 sp<FakeWindowHandle> window =
7213 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7214 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007215 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007216
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007218 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7219 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007220 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007221 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7222 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007223
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007224 // Pilfer pointers from the monitor.
7225 // This should not do anything and the window should continue to receive events.
7226 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00007227
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007228 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007229 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007230 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007231 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007232
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007233 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
7234 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007235}
7236
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007237TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07007238 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007239 sp<FakeWindowHandle> window =
7240 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7241 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007242 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07007243 window->setWindowOffset(20, 40);
7244 window->setWindowTransform(0, 1, -1, 0);
7245
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007246 FakeMonitorReceiver monitor =
7247 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07007248
7249 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007250 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7251 ui::LogicalDisplayId::DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07007252 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007253 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007254 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
7255 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07007256 // Even though window has transform, gesture monitor must not.
7257 ASSERT_EQ(ui::Transform(), event->getTransform());
7258}
7259
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007260TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00007261 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007262 FakeMonitorReceiver monitor =
7263 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00007264
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007265 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007266 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7267 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007268 << "Injection should fail if there is a monitor, but no touchable window";
7269 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00007270}
7271
Linnan Lid8150952024-01-26 18:07:17 +00007272/**
7273 * Two displays
7274 * The first monitor has a foreground window, a monitor
7275 * The second window has only one monitor.
7276 * We first inject a Down event into the first display, this injection should succeed and both
7277 * the foreground window and monitor should receive a down event, then inject a Down event into
7278 * the second display as well, this injection should fail, at this point, the first display
7279 * window and monitor should not receive a cancel or any other event.
7280 * Continue to inject Move and UP events to the first display, the events should be received
7281 * normally by the foreground window and monitor.
7282 */
7283TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
7284 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007285 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7286 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007287
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007288 FakeMonitorReceiver monitor =
7289 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007290 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7291
7292 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007294 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7295 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007296 << "The down event injected into the first display should succeed";
7297
7298 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007299 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007300
7301 ASSERT_EQ(InputEventInjectionResult::FAILED,
7302 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7303 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007304 << "The down event injected into the second display should fail since there's no "
7305 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007306
7307 // Continue to inject event to first display.
7308 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7309 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007310 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007311 << "The move event injected into the first display should succeed";
7312
7313 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007314 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007315
7316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007317 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007318 {110, 220}))
7319 << "The up event injected into the first display should succeed";
7320
7321 window->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007322 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007323
7324 window->assertNoEvents();
7325 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007326 secondMonitor.assertNoEvents();
7327}
7328
7329/**
7330 * Two displays
7331 * There is a monitor and foreground window on each display.
7332 * First, we inject down events into each of the two displays, at this point, the foreground windows
7333 * and monitors on both displays should receive down events.
7334 * At this point, the foreground window of the second display goes away, the gone window should
7335 * receive the cancel event, and the other windows and monitors should not receive any events.
7336 * Inject a move event into the second display. At this point, the injection should fail because
7337 * the second display no longer has a foreground window. At this point, the monitor on the second
7338 * display should receive a cancel event, and any windows or monitors on the first display should
7339 * not receive any events, and any subsequent injection of events into the second display should
7340 * also fail.
7341 * Continue to inject events into the first display, and the events should all be injected
7342 * successfully and received normally.
7343 */
7344TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
7345 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007346 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7347 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007348 sp<FakeWindowHandle> secondWindow =
7349 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
7350 SECOND_DISPLAY_ID);
7351
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007352 FakeMonitorReceiver monitor =
7353 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007354 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7355
7356 // There is a foreground window on both displays.
7357 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7358 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007359 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7360 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007361 << "The down event injected into the first display should succeed";
7362
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007363 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7364 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007365
7366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7367 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7368 {100, 200}))
7369 << "The down event injected into the second display should succeed";
7370
Linnan Lid8150952024-01-26 18:07:17 +00007371 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
7372 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
7373
7374 // Now second window is gone away.
7375 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7376
7377 // The gone window should receive a cancel, and the monitor on the second display should not
7378 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00007379 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
7380 secondMonitor.assertNoEvents();
7381
7382 ASSERT_EQ(InputEventInjectionResult::FAILED,
7383 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7384 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007385 << "The move event injected into the second display should fail because there's no "
7386 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007387 // Now the monitor on the second display should receive a cancel event.
7388 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00007389
7390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7391 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007392 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007393 << "The move event injected into the first display should succeed";
7394
7395 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007396 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007397
7398 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007399 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7400 {110, 220}))
7401 << "The up event injected into the second display should fail because there's no "
7402 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007403
7404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007405 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007406 {110, 220}))
7407 << "The up event injected into the first display should succeed";
7408
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007409 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
7410 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007411
Linnan Lid8150952024-01-26 18:07:17 +00007412 window->assertNoEvents();
7413 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007414 secondWindow->assertNoEvents();
7415 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007416}
7417
7418/**
7419 * One display with transform
7420 * There is a foreground window and a monitor on the display
7421 * Inject down event and move event sequentially, the foreground window and monitor can receive down
7422 * event and move event, then let the foreground window go away, the foreground window receives
7423 * cancel event, inject move event again, the monitor receives cancel event, all the events received
7424 * by the monitor should be with the same transform as the display
7425 */
7426TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
7427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007428 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7429 ui::LogicalDisplayId::DEFAULT);
7430 FakeMonitorReceiver monitor =
7431 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007432
7433 ui::Transform transform;
7434 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7435
7436 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007437 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Linnan Lid8150952024-01-26 18:07:17 +00007438 displayInfo.transform = transform;
7439
7440 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
7441
7442 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007443 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7444 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007445 << "The down event injected should succeed";
7446
7447 window->consumeMotionDown();
7448 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
7449 EXPECT_EQ(transform, downMotionEvent->getTransform());
7450 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
7451
7452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7453 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007454 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007455 << "The move event injected should succeed";
7456
7457 window->consumeMotionMove();
7458 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
7459 EXPECT_EQ(transform, moveMotionEvent->getTransform());
7460 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
7461
7462 // Let foreground window gone
7463 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
7464
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007465 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00007466 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00007467
7468 ASSERT_EQ(InputEventInjectionResult::FAILED,
7469 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007470 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007471 << "The move event injected should failed";
7472 // Now foreground should not receive any events, but monitor should receive a cancel event
7473 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00007474 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
7475 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007476 EXPECT_EQ(ui::LogicalDisplayId::DEFAULT, cancelMotionEvent->getDisplayId());
Linnan Lid8150952024-01-26 18:07:17 +00007477 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
7478
7479 // Other event inject to this display should fail.
7480 ASSERT_EQ(InputEventInjectionResult::FAILED,
7481 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007482 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007483 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00007484 window->assertNoEvents();
7485 monitor.assertNoEvents();
7486}
7487
chaviw81e2bb92019-12-18 15:03:51 -08007488TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007489 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007490 sp<FakeWindowHandle> window =
7491 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7492 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007493
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007494 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08007495
7496 NotifyMotionArgs motionArgs =
7497 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007498 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007499
Prabir Pradhan678438e2023-04-13 19:32:51 +00007500 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08007501 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007502 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007503
7504 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08007505 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08007506 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7507 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
7508 motionArgs.pointerCoords[0].getX() - 10);
7509
Prabir Pradhan678438e2023-04-13 19:32:51 +00007510 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007511 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08007512}
7513
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007514/**
7515 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
7516 * the device default right away. In the test scenario, we check both the default value,
7517 * and the action of enabling / disabling.
7518 */
7519TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07007520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007521 sp<FakeWindowHandle> window =
7522 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7523 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08007524 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007525
7526 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007527 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007528 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007529
7530 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007531 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007532 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007533 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007534
7535 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007536 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007537 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007538 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007539
7540 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007541 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007542 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007543 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07007544 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007545 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007546 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007547 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007548
7549 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007550 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007551 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007552 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007553
7554 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007555 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007556 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007557 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07007558 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007559 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007560 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007561 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007562
7563 window->assertNoEvents();
7564}
7565
Gang Wange9087892020-01-07 12:17:14 -05007566TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007567 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007568 sp<FakeWindowHandle> window =
7569 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7570 ui::LogicalDisplayId::DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05007571
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007572 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007573 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05007574
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007575 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007576 setFocusedWindow(window);
7577
Harry Cutts33476232023-01-30 19:57:29 +00007578 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05007579
Prabir Pradhan678438e2023-04-13 19:32:51 +00007580 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
7581 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05007582
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007583 std::unique_ptr<KeyEvent> event = window->consumeKey();
7584 ASSERT_NE(event, nullptr);
7585 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05007586 ASSERT_NE(verified, nullptr);
7587 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
7588
7589 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
7590 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
7591 ASSERT_EQ(keyArgs.source, verified->source);
7592 ASSERT_EQ(keyArgs.displayId, verified->displayId);
7593
7594 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
7595
7596 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05007597 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007598 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05007599 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
7600 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
7601 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
7602 ASSERT_EQ(0, verifiedKey.repeatCount);
7603}
7604
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007605TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007606 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007607 sp<FakeWindowHandle> window =
7608 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7609 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007610
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007611 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007612
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007613 ui::Transform transform;
7614 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7615
7616 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007617 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007618 displayInfo.transform = transform;
7619
Patrick Williamsd828f302023-04-28 17:52:08 -05007620 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007621
Prabir Pradhan678438e2023-04-13 19:32:51 +00007622 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007623 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007624 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007625 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007626
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007627 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
7628 ASSERT_NE(nullptr, event);
7629 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007630 ASSERT_NE(verified, nullptr);
7631 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
7632
7633 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
7634 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
7635 EXPECT_EQ(motionArgs.source, verified->source);
7636 EXPECT_EQ(motionArgs.displayId, verified->displayId);
7637
7638 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
7639
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007640 const vec2 rawXY =
7641 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
7642 motionArgs.pointerCoords[0].getXYValue());
7643 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
7644 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007645 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007646 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007647 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007648 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
7649 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
7650}
7651
chaviw09c8d2d2020-08-24 15:48:26 -07007652/**
7653 * Ensure that separate calls to sign the same data are generating the same key.
7654 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
7655 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
7656 * tests.
7657 */
7658TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
7659 KeyEvent event = getTestKeyEvent();
7660 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7661
7662 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
7663 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
7664 ASSERT_EQ(hmac1, hmac2);
7665}
7666
7667/**
7668 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
7669 */
7670TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
7671 KeyEvent event = getTestKeyEvent();
7672 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7673 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
7674
7675 verifiedEvent.deviceId += 1;
7676 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7677
7678 verifiedEvent.source += 1;
7679 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7680
7681 verifiedEvent.eventTimeNanos += 1;
7682 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7683
Linnan Li13bf76a2024-05-05 19:18:02 +08007684 verifiedEvent.displayId = ui::LogicalDisplayId{verifiedEvent.displayId.val() + 1};
chaviw09c8d2d2020-08-24 15:48:26 -07007685 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7686
7687 verifiedEvent.action += 1;
7688 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7689
7690 verifiedEvent.downTimeNanos += 1;
7691 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7692
7693 verifiedEvent.flags += 1;
7694 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7695
7696 verifiedEvent.keyCode += 1;
7697 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7698
7699 verifiedEvent.scanCode += 1;
7700 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7701
7702 verifiedEvent.metaState += 1;
7703 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7704
7705 verifiedEvent.repeatCount += 1;
7706 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7707}
7708
Vishnu Nair958da932020-08-21 17:12:37 -07007709TEST_F(InputDispatcherTest, SetFocusedWindow) {
7710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007711 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7712 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007713 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007714 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7715 ui::LogicalDisplayId::DEFAULT);
7716 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007717
7718 // Top window is also focusable but is not granted focus.
7719 windowTop->setFocusable(true);
7720 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007721 mDispatcher->onWindowInfosChanged(
7722 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007723 setFocusedWindow(windowSecond);
7724
7725 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007727 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007728
7729 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007730 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007731 windowTop->assertNoEvents();
7732}
7733
7734TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
7735 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007736 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7737 ui::LogicalDisplayId::DEFAULT);
7738 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007739
7740 window->setFocusable(true);
7741 // Release channel for window is no longer valid.
7742 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007743 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007744 setFocusedWindow(window);
7745
7746 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007747 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007748
7749 // window channel is invalid, so it should not receive any input event.
7750 window->assertNoEvents();
7751}
7752
7753TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
7754 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007755 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7756 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007757 window->setFocusable(false);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007758 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007759
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007760 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007761 setFocusedWindow(window);
7762
7763 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007764 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007765
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007766 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07007767 window->assertNoEvents();
7768}
7769
7770TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
7771 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007772 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7773 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007774 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007775 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7776 ui::LogicalDisplayId::DEFAULT);
7777 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007778
7779 windowTop->setFocusable(true);
7780 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007781 mDispatcher->onWindowInfosChanged(
7782 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007783 setFocusedWindow(windowTop);
7784 windowTop->consumeFocusEvent(true);
7785
Chavi Weingarten847e8512023-03-29 00:26:09 +00007786 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007787 mDispatcher->onWindowInfosChanged(
7788 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007789 windowSecond->consumeFocusEvent(true);
7790 windowTop->consumeFocusEvent(false);
7791
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007793 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007794
7795 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007796 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007797}
7798
Chavi Weingarten847e8512023-03-29 00:26:09 +00007799TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07007800 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007801 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7802 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007803 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007804 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7805 ui::LogicalDisplayId::DEFAULT);
7806 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007807
7808 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00007809 windowSecond->setFocusable(false);
7810 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007811 mDispatcher->onWindowInfosChanged(
7812 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00007813 setFocusedWindow(windowTop);
7814 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07007815
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00007817 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007818
7819 // Event should be dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007820 windowTop->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007821 windowSecond->assertNoEvents();
7822}
7823
7824TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
7825 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007826 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7827 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007828 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007829 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007830 ui::LogicalDisplayId::DEFAULT);
7831 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007832
7833 window->setFocusable(true);
7834 previousFocusedWindow->setFocusable(true);
7835 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007836 mDispatcher->onWindowInfosChanged(
7837 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007838 setFocusedWindow(previousFocusedWindow);
7839 previousFocusedWindow->consumeFocusEvent(true);
7840
7841 // Requesting focus on invisible window takes focus from currently focused window.
7842 setFocusedWindow(window);
7843 previousFocusedWindow->consumeFocusEvent(false);
7844
7845 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007846 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007847 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007848 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007849
7850 // Window does not get focus event or key down.
7851 window->assertNoEvents();
7852
7853 // Window becomes visible.
7854 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007855 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007856
7857 // Window receives focus event.
7858 window->consumeFocusEvent(true);
7859 // Focused window receives key down.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007860 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007861}
7862
Vishnu Nair599f1412021-06-21 10:39:58 -07007863TEST_F(InputDispatcherTest, DisplayRemoved) {
7864 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007865 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "window",
7866 ui::LogicalDisplayId::DEFAULT);
7867 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair599f1412021-06-21 10:39:58 -07007868
7869 // window is granted focus.
7870 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007871 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07007872 setFocusedWindow(window);
7873 window->consumeFocusEvent(true);
7874
7875 // When a display is removed window loses focus.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007876 mDispatcher->displayRemoved(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07007877 window->consumeFocusEvent(false);
7878}
7879
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007880/**
7881 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
7882 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
7883 * of the 'slipperyEnterWindow'.
7884 *
7885 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
7886 * a way so that the touched location is no longer covered by the top window.
7887 *
7888 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
7889 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
7890 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
7891 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
7892 * with ACTION_DOWN).
7893 * Thus, the touch has been transferred from the top window into the bottom window, because the top
7894 * window moved itself away from the touched location and had Flag::SLIPPERY.
7895 *
7896 * Even though the top window moved away from the touched location, it is still obscuring the bottom
7897 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
7898 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
7899 *
7900 * In this test, we ensure that the event received by the bottom window has
7901 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
7902 */
7903TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007904 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007905 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007906
7907 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007908 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007909
7910 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007911 sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7912 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007913 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007914 // Make sure this one overlaps the bottom window
7915 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
7916 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
7917 // one. Windows with the same owner are not considered to be occluding each other.
7918 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
7919
7920 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007921 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7922 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007923 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
7924
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007925 mDispatcher->onWindowInfosChanged(
7926 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007927
7928 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00007929 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007930 AINPUT_SOURCE_TOUCHSCREEN,
7931 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007932 slipperyExitWindow->consumeMotionDown();
7933 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007934 mDispatcher->onWindowInfosChanged(
7935 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007936
Prabir Pradhan678438e2023-04-13 19:32:51 +00007937 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007938 AINPUT_SOURCE_TOUCHSCREEN,
7939 ui::LogicalDisplayId::DEFAULT, {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007940
7941 slipperyExitWindow->consumeMotionCancel();
7942
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007943 slipperyEnterWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007944 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
7945}
7946
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007947/**
7948 * Two windows, one on the left and another on the right. The left window is slippery. The right
7949 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
7950 * touch moves from the left window into the right window, the gesture should continue to go to the
7951 * left window. Touch shouldn't slip because the right window can't receive touches. This test
7952 * reproduces a crash.
7953 */
7954TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
7955 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7956
7957 sp<FakeWindowHandle> leftSlipperyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007958 sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
7959 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007960 leftSlipperyWindow->setSlippery(true);
7961 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
7962
7963 sp<FakeWindowHandle> rightDropTouchesWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007964 sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
7965 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007966 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
7967 rightDropTouchesWindow->setDropInput(true);
7968
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007969 mDispatcher->onWindowInfosChanged(
7970 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007971
7972 // Start touch in the left window
7973 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7974 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7975 .build());
7976 leftSlipperyWindow->consumeMotionDown();
7977
7978 // And move it into the right window
7979 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7980 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7981 .build());
7982
7983 // Since the right window isn't eligible to receive input, touch does not slip.
7984 // The left window continues to receive the gesture.
7985 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7986 rightDropTouchesWindow->assertNoEvents();
7987}
7988
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007989/**
7990 * A single window is on screen first. Touch is injected into that window. Next, a second window
7991 * appears. Since the first window is slippery, touch will move from the first window to the second.
7992 */
7993TEST_F(InputDispatcherTest, InjectedTouchSlips) {
7994 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7995 sp<FakeWindowHandle> originalWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007996 sp<FakeWindowHandle>::make(application, mDispatcher, "Original",
7997 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007998 originalWindow->setFrame(Rect(0, 0, 200, 200));
7999 originalWindow->setSlippery(true);
8000
8001 sp<FakeWindowHandle> appearingWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008002 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing",
8003 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008004 appearingWindow->setFrame(Rect(0, 0, 200, 200));
8005
8006 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
8007
8008 // Touch down on the original window
8009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8010 injectMotionEvent(*mDispatcher,
8011 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8012 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
8013 .build()));
8014 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8015
8016 // Now, a new window appears. This could be, for example, a notification shade that appears
8017 // after user starts to drag down on the launcher window.
8018 mDispatcher->onWindowInfosChanged(
8019 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
8020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8021 injectMotionEvent(*mDispatcher,
8022 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8023 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
8024 .build()));
8025 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8026 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8028 injectMotionEvent(*mDispatcher,
8029 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8030 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
8031 .build()));
8032 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
8033
8034 originalWindow->assertNoEvents();
8035 appearingWindow->assertNoEvents();
8036}
8037
Linnan Li49b2b202024-04-12 12:46:40 +08008038/**
8039 * Three windows:
8040 * - left window, which has FLAG_SLIPPERY, so it supports slippery exit
8041 * - right window
8042 * - spy window
8043 * The three windows do not overlap.
8044 *
8045 * We have two devices reporting events:
8046 * - Device A reports ACTION_DOWN, which lands in the left window
8047 * - Device B reports ACTION_DOWN, which lands in the spy window.
8048 * - Now, device B reports ACTION_MOVE events which move to the right window.
8049 *
8050 * The right window should not receive any events because the spy window is not a foreground window,
8051 * and also it does not support slippery touches.
8052 */
8053TEST_F(InputDispatcherTest, MultiDeviceSpyWindowSlipTest) {
8054 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8055 sp<FakeWindowHandle> leftWindow =
8056 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008057 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008058 leftWindow->setFrame(Rect(0, 0, 100, 100));
8059 leftWindow->setSlippery(true);
8060
8061 sp<FakeWindowHandle> rightWindow =
8062 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008063 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008064 rightWindow->setFrame(Rect(100, 0, 200, 100));
8065
8066 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008067 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8068 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008069 spyWindow->setFrame(Rect(200, 0, 300, 100));
8070 spyWindow->setSpy(true);
8071 spyWindow->setTrustedOverlay(true);
8072
8073 mDispatcher->onWindowInfosChanged(
8074 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *spyWindow->getInfo()}, {}, 0, 0});
8075
8076 const DeviceId deviceA = 9;
8077 const DeviceId deviceB = 3;
8078
8079 // Tap on left window with device A
8080 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8081 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8082 .deviceId(deviceA)
8083 .build());
8084 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8085
8086 // Tap on spy window with device B
8087 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8088 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
8089 .deviceId(deviceB)
8090 .build());
8091 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8092
8093 // Move to right window with device B. Touches should not slip to the right window, because spy
8094 // window is not a foreground window, and it does not have FLAG_SLIPPERY
8095 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8096 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8097 .deviceId(deviceB)
8098 .build());
8099 leftWindow->assertNoEvents();
8100 rightWindow->assertNoEvents();
8101 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
8102}
8103
8104/**
8105 * Three windows arranged horizontally and without any overlap.
8106 * The left and right windows have FLAG_SLIPPERY. The middle window does not have any special flags.
8107 *
8108 * We have two devices reporting events:
8109 * - Device A reports ACTION_DOWN which lands in the left window
8110 * - Device B reports ACTION_DOWN which lands in the right window
8111 * - Device B reports ACTION_MOVE that shifts to the middle window.
8112 * This should cause touches for Device B to slip from the right window to the middle window.
8113 * The right window should receive ACTION_CANCEL for device B and the
8114 * middle window should receive down event for Device B.
8115 * If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
8116 */
8117TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
Siarhei Vishniakoudd56df12024-05-20 14:56:38 -07008118 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
Linnan Li49b2b202024-04-12 12:46:40 +08008119 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8120 sp<FakeWindowHandle> leftWindow =
8121 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008122 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008123 leftWindow->setFrame(Rect(0, 0, 100, 100));
8124 leftWindow->setSlippery(true);
8125
8126 sp<FakeWindowHandle> middleWindow =
8127 sp<FakeWindowHandle>::make(application, mDispatcher, "middle window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008128 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008129 middleWindow->setFrame(Rect(100, 0, 200, 100));
8130
8131 sp<FakeWindowHandle> rightWindow =
8132 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008133 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008134 rightWindow->setFrame(Rect(200, 0, 300, 100));
8135 rightWindow->setSlippery(true);
8136
8137 mDispatcher->onWindowInfosChanged(
8138 {{*leftWindow->getInfo(), *middleWindow->getInfo(), *rightWindow->getInfo()},
8139 {},
8140 0,
8141 0});
8142
8143 const DeviceId deviceA = 9;
8144 const DeviceId deviceB = 3;
8145
8146 // Tap on left window with device A
8147 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8148 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8149 .deviceId(deviceA)
8150 .build());
8151 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8152
8153 // Tap on right window with device B
8154 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8155 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
8156 .deviceId(deviceB)
8157 .build());
8158 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8159
8160 // Move to middle window with device B. Touches should slip to middle window, because right
8161 // window is a foreground window that's associated with device B and has FLAG_SLIPPERY.
8162 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8163 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8164 .deviceId(deviceB)
8165 .build());
8166 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
8167 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8168
8169 // Move to middle window with device A. Touches should slip to middle window, because left
8170 // window is a foreground window that's associated with device A and has FLAG_SLIPPERY.
8171 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8172 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8173 .deviceId(deviceA)
8174 .build());
8175 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceA)));
8176 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8177
8178 // Ensure that middle window can receive the remaining move events.
8179 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8180 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
8181 .deviceId(deviceB)
8182 .build());
8183 leftWindow->assertNoEvents();
8184 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
8185 rightWindow->assertNoEvents();
8186}
8187
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008188TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008189 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008190 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8191
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008192 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
8193 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008194 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008195 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008196
8197 sp<FakeWindowHandle> rightSpy =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008198 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy",
8199 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008200 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008201 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008202 rightSpy->setSpy(true);
8203 rightSpy->setTrustedOverlay(true);
8204
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008205 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
8206 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008207 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008208 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008209
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008210 mDispatcher->onWindowInfosChanged(
8211 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008212
8213 // Touch in the left window
8214 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8215 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8216 .build());
8217 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
8218 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008219 ASSERT_NO_FATAL_FAILURE(
8220 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008221
8222 // Touch another finger over the right windows
8223 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8224 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8225 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8226 .build());
8227 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
8228 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
8229 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
8230 mDispatcher->waitForIdle();
8231 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008232 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
8233 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008234
8235 // Release finger over left window. The UP actions are not treated as device interaction.
8236 // The windows that did not receive the UP pointer will receive MOVE events, but since this
8237 // is part of the UP action, we do not treat this as device interaction.
8238 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
8239 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8240 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8241 .build());
8242 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
8243 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8244 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8245 mDispatcher->waitForIdle();
8246 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8247
8248 // Move remaining finger
8249 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8250 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8251 .build());
8252 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8253 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8254 mDispatcher->waitForIdle();
8255 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008256 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008257
8258 // Release all fingers
8259 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8260 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8261 .build());
8262 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
8263 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
8264 mDispatcher->waitForIdle();
8265 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8266}
8267
8268TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
8269 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8270
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008271 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8272 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008273 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008274 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008275
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008276 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008277 setFocusedWindow(window);
8278 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
8279
8280 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008281 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008282 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008283 ASSERT_NO_FATAL_FAILURE(
8284 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008285
8286 // The UP actions are not treated as device interaction.
8287 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008288 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008289 mDispatcher->waitForIdle();
8290 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8291}
8292
Prabir Pradhan5893d362023-11-17 04:30:40 +00008293TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
8294 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8295
8296 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008297 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008298 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008299 sp<FakeWindowHandle> right =
8300 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
8301 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008302 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008303 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8304 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008305 spy->setFrame(Rect(0, 0, 200, 100));
8306 spy->setTrustedOverlay(true);
8307 spy->setSpy(true);
8308
8309 mDispatcher->onWindowInfosChanged(
8310 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
8311
8312 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008313 NotifyMotionArgs notifyArgs =
8314 generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8315 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008316 mDispatcher->notifyMotion(notifyArgs);
8317
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008318 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008319 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
8320 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008321 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008322 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8323 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008324 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008325 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8326
8327 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008328 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8329 ui::LogicalDisplayId::DEFAULT, {PointF{150, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008330 mDispatcher->notifyMotion(notifyArgs);
8331
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008332 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008333 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
8334 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008335 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008336 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8337 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008338 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008339 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8340
8341 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
8342}
8343
Linnan Liccf6ce32024-04-11 20:32:13 +08008344/**
8345 * When a device reports a DOWN event, which lands in a window that supports splits, and then the
8346 * device then reports a POINTER_DOWN, which lands in the location of a non-existing window, then
8347 * the previous window should receive this event and not be dropped.
8348 */
8349TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
8350 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008351 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8352 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008353 window->setFrame(Rect(0, 0, 100, 100));
8354 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8355
8356 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8357 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8358 .build());
8359
8360 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
8361
8362 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8363 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8364 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
8365 .build());
8366
8367 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_1_DOWN)));
8368}
8369
8370/**
8371 * When deviceA reports a DOWN event, which lands in a window that supports splits, and then deviceB
8372 * also reports a DOWN event, which lands in the location of a non-existing window, then the
8373 * previous window should receive deviceB's event and it should be dropped.
8374 */
8375TEST_F(InputDispatcherMultiDeviceTest, SecondDeviceDownEventDroppedWithoutWindowTarget) {
8376 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008377 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8378 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008379 window->setFrame(Rect(0, 0, 100, 100));
8380 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8381
8382 const DeviceId deviceA = 9;
8383 const DeviceId deviceB = 3;
8384
8385 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8386 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8387 .deviceId(deviceA)
8388 .build());
8389 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8390
8391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8392 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
8393 .deviceId(deviceB)
8394 .build());
8395 window->assertNoEvents();
8396}
8397
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008398class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
8399protected:
8400 std::shared_ptr<FakeApplicationHandle> mApp;
8401 sp<FakeWindowHandle> mWindow;
8402
8403 virtual void SetUp() override {
8404 InputDispatcherTest::SetUp();
8405
8406 mApp = std::make_shared<FakeApplicationHandle>();
8407
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008408 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window",
8409 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008410 mWindow->setFrame(Rect(0, 0, 100, 100));
8411
8412 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8413 setFocusedWindow(mWindow);
8414 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
8415 }
8416
8417 void setFallback(int32_t keycode) {
8418 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
8419 return KeyEventBuilder(event).keyCode(keycode).build();
8420 });
8421 }
8422
8423 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008424 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
8425 ASSERT_NE(nullptr, event);
8426 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008427 }
8428};
8429
8430TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
8431 mDispatcher->notifyKey(
8432 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8433 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8434 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8435}
8436
8437TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
8438 mDispatcher->notifyKey(
8439 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8440 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8441 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8442}
8443
8444TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
8445 mDispatcher->notifyKey(
8446 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8447
8448 // Do not handle this key event.
8449 consumeKey(/*handled=*/false,
8450 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8451 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8452
8453 // Since the policy did not request any fallback to be generated, ensure there are no events.
8454 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8455}
8456
8457TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
8458 setFallback(AKEYCODE_B);
8459 mDispatcher->notifyKey(
8460 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8461
8462 // Do not handle this key event.
8463 consumeKey(/*handled=*/false,
8464 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8465
8466 // Since the key was not handled, ensure the fallback event was dispatched instead.
8467 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8468 consumeKey(/*handled=*/true,
8469 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8470 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8471
8472 // Release the original key, and ensure the fallback key is also released.
8473 mDispatcher->notifyKey(
8474 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8475 consumeKey(/*handled=*/false,
8476 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8477 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8478 consumeKey(/*handled=*/true,
8479 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8480 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8481
8482 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8483 mWindow->assertNoEvents();
8484}
8485
8486TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
8487 setFallback(AKEYCODE_B);
8488 mDispatcher->notifyKey(
8489 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8490
8491 // Do not handle this key event, but handle the fallback.
8492 consumeKey(/*handled=*/false,
8493 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8494 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8495 consumeKey(/*handled=*/true,
8496 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8497 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8498
8499 // Release the original key, and ensure the fallback key is also released.
8500 mDispatcher->notifyKey(
8501 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8502 // But this time, the app handles the original key.
8503 consumeKey(/*handled=*/true,
8504 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8505 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8506 // Ensure the fallback key is canceled.
8507 consumeKey(/*handled=*/true,
8508 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8509 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8510
8511 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8512 mWindow->assertNoEvents();
8513}
8514
8515TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
8516 setFallback(AKEYCODE_B);
8517 mDispatcher->notifyKey(
8518 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8519
8520 // Do not handle this key event.
8521 consumeKey(/*handled=*/false,
8522 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8523 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8524 // App does not handle the fallback either, so ensure another fallback is not generated.
8525 setFallback(AKEYCODE_C);
8526 consumeKey(/*handled=*/false,
8527 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8528 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8529
8530 // Release the original key, and ensure the fallback key is also released.
8531 setFallback(AKEYCODE_B);
8532 mDispatcher->notifyKey(
8533 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8534 consumeKey(/*handled=*/false,
8535 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8536 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8537 consumeKey(/*handled=*/false,
8538 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8539 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8540
8541 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8542 mWindow->assertNoEvents();
8543}
8544
8545TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
8546 setFallback(AKEYCODE_B);
8547 mDispatcher->notifyKey(
8548 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8549
8550 // Do not handle this key event, so fallback is generated.
8551 consumeKey(/*handled=*/false,
8552 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8553 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8554 consumeKey(/*handled=*/true,
8555 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8556 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8557
8558 // Release the original key, but assume the policy is misbehaving and it
8559 // generates an inconsistent fallback to the one from the DOWN event.
8560 setFallback(AKEYCODE_C);
8561 mDispatcher->notifyKey(
8562 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8563 consumeKey(/*handled=*/false,
8564 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8565 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8566 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
8567 consumeKey(/*handled=*/true,
8568 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8569 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8570
8571 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8572 mWindow->assertNoEvents();
8573}
8574
8575TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
8576 setFallback(AKEYCODE_B);
8577 mDispatcher->notifyKey(
8578 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8579
8580 // Do not handle this key event, so fallback is generated.
8581 consumeKey(/*handled=*/false,
8582 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8583 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8584 consumeKey(/*handled=*/true,
8585 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8586 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8587
8588 // The original key is canceled.
8589 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
8590 .keyCode(AKEYCODE_A)
8591 .addFlag(AKEY_EVENT_FLAG_CANCELED)
8592 .build());
8593 consumeKey(/*handled=*/false,
8594 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8595 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8596 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8597 // Ensure the fallback key is also canceled due to the original key being canceled.
8598 consumeKey(/*handled=*/true,
8599 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8600 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8601
8602 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8603 mWindow->assertNoEvents();
8604}
8605
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008606TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00008607 setFallback(AKEYCODE_B);
8608 mDispatcher->notifyKey(
8609 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8610
8611 // Do not handle this key event.
8612 consumeKey(/*handled=*/false,
8613 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8614 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8615 consumeKey(/*handled=*/true,
8616 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8617 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8618
8619 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8620 // When the unhandled key is reported to the policy next, remove the input channel.
8621 mDispatcher->removeInputChannel(mWindow->getToken());
8622 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8623 });
8624 // Release the original key, and let the app now handle the previously unhandled key.
8625 // This should result in the previously generated fallback key to be cancelled.
8626 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
8627 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
8628 // without holding the lock, because it need to synchronously fetch the fallback key. While in
8629 // the policy call, we will now remove the input channel. Once the policy call returns, the
8630 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
8631 // not cause any crashes.
8632 mDispatcher->notifyKey(
8633 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8634 consumeKey(/*handled=*/true,
8635 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8636 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8637}
8638
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008639TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
8640 setFallback(AKEYCODE_B);
8641 mDispatcher->notifyKey(
8642 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8643
8644 // Do not handle this key event.
8645 consumeKey(/*handled=*/false,
8646 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8647 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8648 consumeKey(/*handled=*/true,
8649 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8650 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8651
8652 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8653 // When the unhandled key is reported to the policy next, remove the window.
8654 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8655 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8656 });
8657 // Release the original key, which the app will not handle. When this unhandled key is reported
8658 // to the policy, the window will be removed.
8659 mDispatcher->notifyKey(
8660 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8661 consumeKey(/*handled=*/false,
8662 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8663 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8664
8665 // Since the window was removed, it loses focus, and the channel state will be reset.
8666 consumeKey(/*handled=*/true,
8667 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8668 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8669 mWindow->consumeFocusEvent(false);
8670 mWindow->assertNoEvents();
8671}
8672
8673TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
8674 setFallback(AKEYCODE_B);
8675 mDispatcher->notifyKey(
8676 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8677
8678 // Do not handle this key event.
8679 consumeKey(/*handled=*/false,
8680 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8681 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8682 const auto [seq, event] = mWindow->receiveEvent();
8683 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
8684 ASSERT_EQ(event->getType(), InputEventType::KEY);
8685 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
8686 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8687 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8688
8689 // Remove the window now, which should generate a cancellations and make the window lose focus.
8690 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8691 consumeKey(/*handled=*/true,
8692 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8693 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8694 consumeKey(/*handled=*/true,
8695 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8696 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8697 mWindow->consumeFocusEvent(false);
8698
8699 // Finish the event by reporting it as handled.
8700 mWindow->finishEvent(*seq);
8701 mWindow->assertNoEvents();
8702}
8703
Garfield Tan1c7bc862020-01-28 13:24:04 -08008704class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
8705protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08008706 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
8707 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008708
Chris Yea209fde2020-07-22 13:54:51 -07008709 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008710 sp<FakeWindowHandle> mWindow;
8711
8712 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00008713 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008714
Prabir Pradhandae52792023-12-15 07:36:40 +00008715 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008716 setUpWindow();
8717 }
8718
8719 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07008720 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008721 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window",
8722 ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008723
Vishnu Nair47074b82020-08-14 11:54:47 -07008724 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008725 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008726 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008727 mWindow->consumeFocusEvent(true);
8728 }
8729
Chris Ye2ad95392020-09-01 13:44:44 -07008730 void sendAndConsumeKeyDown(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008731 NotifyKeyArgs keyArgs =
8732 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008733 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008734 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008735 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008736
8737 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008738 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008739 }
8740
8741 void expectKeyRepeatOnce(int32_t repeatCount) {
8742 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008743 mWindow->consumeKeyEvent(
8744 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008745 }
8746
Chris Ye2ad95392020-09-01 13:44:44 -07008747 void sendAndConsumeKeyUp(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008748 NotifyKeyArgs keyArgs =
8749 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008750 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008751 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008752 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008753
8754 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008755 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008756 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008757 }
Hu Guofe3c8f12023-09-22 17:20:15 +08008758
8759 void injectKeyRepeat(int32_t repeatCount) {
8760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008761 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount,
8762 ui::LogicalDisplayId::DEFAULT))
Hu Guofe3c8f12023-09-22 17:20:15 +08008763 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8764 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08008765};
8766
8767TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00008768 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008769 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8770 expectKeyRepeatOnce(repeatCount);
8771 }
8772}
8773
8774TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00008775 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008776 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8777 expectKeyRepeatOnce(repeatCount);
8778 }
Harry Cutts33476232023-01-30 19:57:29 +00008779 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008780 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08008781 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8782 expectKeyRepeatOnce(repeatCount);
8783 }
8784}
8785
8786TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008787 sendAndConsumeKeyDown(/*deviceId=*/1);
8788 expectKeyRepeatOnce(/*repeatCount=*/1);
8789 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008790 mWindow->assertNoEvents();
8791}
8792
8793TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008794 sendAndConsumeKeyDown(/*deviceId=*/1);
8795 expectKeyRepeatOnce(/*repeatCount=*/1);
8796 sendAndConsumeKeyDown(/*deviceId=*/2);
8797 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008798 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00008799 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008800 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00008801 expectKeyRepeatOnce(/*repeatCount=*/2);
8802 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07008803 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00008804 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008805 mWindow->assertNoEvents();
8806}
8807
8808TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008809 sendAndConsumeKeyDown(/*deviceId=*/1);
8810 expectKeyRepeatOnce(/*repeatCount=*/1);
8811 sendAndConsumeKeyDown(/*deviceId=*/2);
8812 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008813 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00008814 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008815 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08008816 mWindow->assertNoEvents();
8817}
8818
liushenxiang42232912021-05-21 20:24:09 +08008819TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
8820 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00008821 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008822 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008823 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
liushenxiang42232912021-05-21 20:24:09 +08008824 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
8825 mWindow->assertNoEvents();
8826}
8827
Garfield Tan1c7bc862020-01-28 13:24:04 -08008828TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008829 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008830 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008831 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008832 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8833 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008834 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008835 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008836 }
8837}
8838
8839TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008840 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008841 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008842
8843 std::unordered_set<int32_t> idSet;
8844 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008845 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8846 ASSERT_NE(nullptr, repeatEvent);
8847 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008848 EXPECT_EQ(idSet.end(), idSet.find(id));
8849 idSet.insert(id);
8850 }
8851}
8852
Hu Guofe3c8f12023-09-22 17:20:15 +08008853TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
8854 injectKeyRepeat(0);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008855 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Hu Guofe3c8f12023-09-22 17:20:15 +08008856 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
8857 expectKeyRepeatOnce(repeatCount);
8858 }
8859 injectKeyRepeat(1);
8860 // Expect repeatCount to be 3 instead of 1
8861 expectKeyRepeatOnce(3);
8862}
8863
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008864/* Test InputDispatcher for MultiDisplay */
8865class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
8866public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008867 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008868 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08008869
Chris Yea209fde2020-07-22 13:54:51 -07008870 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008871 windowInPrimary = sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1",
8872 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008873
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008874 // Set focus window for primary display, but focused display would be second one.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008875 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07008876 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008877 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
8878
Vishnu Nair958da932020-08-21 17:12:37 -07008879 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008880 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08008881
Chris Yea209fde2020-07-22 13:54:51 -07008882 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008883 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008884 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008885 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008886 // Set focus display to second one.
8887 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +00008888 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
8889
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008890 // Set focus window for second display.
8891 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07008892 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008893 mDispatcher->onWindowInfosChanged(
8894 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008895 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008896 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008897 }
8898
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008899 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008900 InputDispatcherTest::TearDown();
8901
Chris Yea209fde2020-07-22 13:54:51 -07008902 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008903 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07008904 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008905 windowInSecondary.clear();
8906 }
8907
8908protected:
Chris Yea209fde2020-07-22 13:54:51 -07008909 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008910 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07008911 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008912 sp<FakeWindowHandle> windowInSecondary;
8913};
8914
8915TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
8916 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008918 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8919 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008920 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008921 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08008922 windowInSecondary->assertNoEvents();
8923
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008924 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008926 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008927 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08008928 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08008929 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08008930}
8931
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008932TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08008933 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008935 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008936 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008937 windowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08008938 windowInSecondary->assertNoEvents();
8939
8940 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008942 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08008943 windowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008944 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hungb92218b2018-08-14 12:00:21 +08008945
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008946 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008947 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08008948
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008949 // Old focus should receive a cancel event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008950 windowInSecondary->consumeKeyUp(ui::LogicalDisplayId::INVALID, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08008951
8952 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008953 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08008954 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008955 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08008956 windowInSecondary->assertNoEvents();
8957}
8958
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008959// Test per-display input monitors for motion event.
8960TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08008961 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008962 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08008963 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008964 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008965
8966 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008967 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008968 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8969 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008970 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008971 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
8972 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008973 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008974 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008975
8976 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008977 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008978 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008979 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008980 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008981 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08008982 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08008983 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008984
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08008985 // Lift up the touch from the second display
8986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008987 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08008988 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8989 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
8990 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
8991
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008992 // Test inject a non-pointer motion event.
8993 // If specific a display, it will dispatch to the focused window of particular display,
8994 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008995 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008996 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL,
8997 ui::LogicalDisplayId::INVALID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008998 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008999 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009000 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009001 windowInSecondary->consumeMotionDown(ui::LogicalDisplayId::INVALID);
9002 monitorInSecondary.consumeMotionDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009003}
9004
9005// Test per-display input monitors for key event.
9006TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009007 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08009008 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009009 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08009010 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009011 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009012
9013 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009015 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009016 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009017 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009018 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
9019 monitorInSecondary.consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009020}
9021
Vishnu Nair958da932020-08-21 17:12:37 -07009022TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
9023 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009024 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2",
9025 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009026 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009027 mDispatcher->onWindowInfosChanged(
9028 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
9029 *windowInSecondary->getInfo()},
9030 {},
9031 0,
9032 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009033 setFocusedWindow(secondWindowInPrimary);
9034 windowInPrimary->consumeFocusEvent(false);
9035 secondWindowInPrimary->consumeFocusEvent(true);
9036
9037 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009039 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009040 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009041 windowInPrimary->assertNoEvents();
9042 windowInSecondary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009043 secondWindowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009044}
9045
Arthur Hungdfd528e2021-12-08 13:23:04 +00009046TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
9047 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009048 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009049 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009050 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009051
9052 // Test touch down on primary display.
9053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009054 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9055 ui::LogicalDisplayId::DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009057 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9058 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009059
9060 // Test touch down on second display.
9061 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009062 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9064 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
9065 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
9066
9067 // Trigger cancel touch.
9068 mDispatcher->cancelCurrentTouch();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009069 windowInPrimary->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
9070 monitorInPrimary.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009071 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
9072 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
9073
9074 // Test inject a move motion event, no window/monitor should receive the event.
9075 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009076 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009077 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009078 << "Inject motion event should return InputEventInjectionResult::FAILED";
9079 windowInPrimary->assertNoEvents();
9080 monitorInPrimary.assertNoEvents();
9081
9082 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009083 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00009084 SECOND_DISPLAY_ID, {110, 200}))
9085 << "Inject motion event should return InputEventInjectionResult::FAILED";
9086 windowInSecondary->assertNoEvents();
9087 monitorInSecondary.assertNoEvents();
9088}
9089
Hu Guocb134f12023-12-23 13:42:44 +00009090/**
9091 * Send a key to the primary display and to the secondary display.
9092 * Then cause the key on the primary display to be canceled by sending in a stale key.
9093 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
9094 * does not get canceled.
9095 */
9096TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
9097 // Send a key down on primary display
9098 mDispatcher->notifyKey(
9099 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009100 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009101 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9102 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009103 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
9104 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00009105 windowInSecondary->assertNoEvents();
9106
9107 // Send a key down on second display
9108 mDispatcher->notifyKey(
9109 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9110 .displayId(SECOND_DISPLAY_ID)
9111 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9112 .build());
9113 windowInSecondary->consumeKeyEvent(
9114 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
9115 windowInPrimary->assertNoEvents();
9116
9117 // Send a valid key up event on primary display that will be dropped because it is stale
9118 NotifyKeyArgs staleKeyUp =
9119 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009120 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009121 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9122 .build();
9123 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
9124 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
9125 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
9126 mDispatcher->notifyKey(staleKeyUp);
9127
9128 // Only the key gesture corresponding to the dropped event should receive the cancel event.
9129 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
9130 // receive any events.
9131 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009132 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
Hu Guocb134f12023-12-23 13:42:44 +00009133 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
9134 windowInSecondary->assertNoEvents();
9135}
9136
9137/**
9138 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
9139 */
9140TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
9141 // Send touch down on primary display.
9142 mDispatcher->notifyMotion(
9143 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9144 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009145 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009146 .build());
9147 windowInPrimary->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009148 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00009149 windowInSecondary->assertNoEvents();
9150
9151 // Send touch down on second display.
9152 mDispatcher->notifyMotion(
9153 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9154 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9155 .displayId(SECOND_DISPLAY_ID)
9156 .build());
9157 windowInPrimary->assertNoEvents();
9158 windowInSecondary->consumeMotionEvent(
9159 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
9160
9161 // inject a valid MotionEvent on primary display that will be stale when it arrives.
9162 NotifyMotionArgs staleMotionUp =
9163 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009164 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009165 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9166 .build();
9167 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
9168 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
9169 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
9170 mDispatcher->notifyMotion(staleMotionUp);
9171
9172 // For stale motion events, we let the gesture to complete. This behaviour is different from key
9173 // events, where we would cancel the current keys instead.
9174 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
9175 windowInSecondary->assertNoEvents();
9176}
9177
Jackal Guof9696682018-10-05 12:23:23 +08009178class InputFilterTest : public InputDispatcherTest {
9179protected:
Linnan Li13bf76a2024-05-05 19:18:02 +08009180 void testNotifyMotion(ui::LogicalDisplayId displayId, bool expectToBeFiltered,
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009181 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08009182 NotifyMotionArgs motionArgs;
9183
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009184 motionArgs =
9185 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009186 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009187 motionArgs =
9188 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009189 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009190 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08009191 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009192 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009193 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08009194 } else {
9195 mFakePolicy->assertFilterInputEventWasNotCalled();
9196 }
9197 }
9198
9199 void testNotifyKey(bool expectToBeFiltered) {
9200 NotifyKeyArgs keyArgs;
9201
9202 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009203 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009204 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009205 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009206 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08009207
9208 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08009209 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009210 } else {
9211 mFakePolicy->assertFilterInputEventWasNotCalled();
9212 }
9213 }
9214};
9215
9216// Test InputFilter for MotionEvent
9217TEST_F(InputFilterTest, MotionEvent_InputFilter) {
9218 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009219 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009220 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009221
9222 // Enable InputFilter
9223 mDispatcher->setInputFilterEnabled(true);
9224 // Test touch on both primary and second display, and check if both events are filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009225 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009226 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009227
9228 // Disable InputFilter
9229 mDispatcher->setInputFilterEnabled(false);
9230 // Test touch on both primary and second display, and check if both events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009231 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009232 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009233}
9234
9235// Test InputFilter for KeyEvent
9236TEST_F(InputFilterTest, KeyEvent_InputFilter) {
9237 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009238 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009239
9240 // Enable InputFilter
9241 mDispatcher->setInputFilterEnabled(true);
9242 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009243 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009244
9245 // Disable InputFilter
9246 mDispatcher->setInputFilterEnabled(false);
9247 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009248 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009249}
9250
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009251// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
9252// logical display coordinate space.
9253TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
9254 ui::Transform firstDisplayTransform;
9255 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
9256 ui::Transform secondDisplayTransform;
9257 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
9258
9259 std::vector<gui::DisplayInfo> displayInfos(2);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009260 displayInfos[0].displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009261 displayInfos[0].transform = firstDisplayTransform;
9262 displayInfos[1].displayId = SECOND_DISPLAY_ID;
9263 displayInfos[1].transform = secondDisplayTransform;
9264
Patrick Williamsd828f302023-04-28 17:52:08 -05009265 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009266
9267 // Enable InputFilter
9268 mDispatcher->setInputFilterEnabled(true);
9269
9270 // Ensure the correct transforms are used for the displays.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009271 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true,
9272 firstDisplayTransform);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009273 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009274}
9275
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009276class InputFilterInjectionPolicyTest : public InputDispatcherTest {
9277protected:
9278 virtual void SetUp() override {
9279 InputDispatcherTest::SetUp();
9280
9281 /**
9282 * We don't need to enable input filter to test the injected event policy, but we enabled it
9283 * here to make the tests more realistic, since this policy only matters when inputfilter is
9284 * on.
9285 */
9286 mDispatcher->setInputFilterEnabled(true);
9287
9288 std::shared_ptr<InputApplicationHandle> application =
9289 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009290 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009291 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009292
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009293 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009294 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009295 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009296 setFocusedWindow(mWindow);
9297 mWindow->consumeFocusEvent(true);
9298 }
9299
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009300 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9301 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009302 KeyEvent event;
9303
9304 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9305 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009306 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
9307 AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009308 const int32_t additionalPolicyFlags =
9309 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
9310 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009311 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009312 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009313 policyFlags | additionalPolicyFlags));
9314
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009315 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009316 }
9317
9318 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9319 int32_t flags) {
9320 MotionEvent event;
9321 PointerProperties pointerProperties[1];
9322 PointerCoords pointerCoords[1];
9323 pointerProperties[0].clear();
9324 pointerProperties[0].id = 0;
9325 pointerCoords[0].clear();
9326 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
9327 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
9328
9329 ui::Transform identityTransform;
9330 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9331 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
9332 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
9333 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
9334 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07009335 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07009336 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00009337 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009338
9339 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
9340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009341 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009342 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009343 policyFlags | additionalPolicyFlags));
9344
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009345 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009346 }
9347
9348private:
9349 sp<FakeWindowHandle> mWindow;
9350};
9351
9352TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009353 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
9354 // filter. Without it, the event will no different from a regularly injected event, and the
9355 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00009356 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
9357 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009358}
9359
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009360TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009361 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009362 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009363 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
9364}
9365
9366TEST_F(InputFilterInjectionPolicyTest,
9367 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
9368 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009369 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009370 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009371}
9372
9373TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00009374 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
9375 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009376}
9377
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009378class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
9379protected:
9380 virtual void SetUp() override {
9381 InputDispatcherTest::SetUp();
9382
9383 std::shared_ptr<FakeApplicationHandle> application =
9384 std::make_shared<FakeApplicationHandle>();
9385 application->setDispatchingTimeout(100ms);
9386 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009387 ui::LogicalDisplayId::DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00009388 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009389 mWindow->setDispatchingTimeout(100ms);
9390 mWindow->setFocusable(true);
9391
9392 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009393 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009394
9395 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
9396 setFocusedWindow(mWindow);
9397 mWindow->consumeFocusEvent(true);
9398 }
9399
Linnan Li13bf76a2024-05-05 19:18:02 +08009400 void notifyAndConsumeMotion(int32_t action, uint32_t source, ui::LogicalDisplayId displayId,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009401 nsecs_t eventTime) {
9402 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
9403 .displayId(displayId)
9404 .eventTime(eventTime)
9405 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9406 .build());
9407 mWindow->consumeMotionEvent(WithMotionAction(action));
9408 }
9409
9410private:
9411 sp<FakeWindowHandle> mWindow;
9412};
9413
9414TEST_F_WITH_FLAGS(
9415 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
9416 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9417 rate_limit_user_activity_poke_in_dispatcher))) {
9418 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
9419
9420 // First event of type TOUCH. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009421 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009422 milliseconds_to_nanoseconds(50));
9423 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009424 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
9425 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009426
9427 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009428 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009429 milliseconds_to_nanoseconds(130));
9430 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009431 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
9432 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009433
9434 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009435 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9436 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009437 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009438 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
9439 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009440
9441 // Within 50ns of previous TOUCH event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009442 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009443 milliseconds_to_nanoseconds(140));
9444 mFakePolicy->assertUserActivityNotPoked();
9445
9446 // Within 50ns of previous OTHER event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009447 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9448 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009449 mFakePolicy->assertUserActivityNotPoked();
9450
9451 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
9452 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009453 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009454 milliseconds_to_nanoseconds(160));
9455 mFakePolicy->assertUserActivityNotPoked();
9456
9457 // 65ns > 50ns has passed since previous OTHER event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009458 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9459 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009460 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009461 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
9462 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009463
9464 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009465 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009466 milliseconds_to_nanoseconds(300));
9467 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009468 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
9469 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009470
9471 // Assert that there's no more user activity poke event.
9472 mFakePolicy->assertUserActivityNotPoked();
9473}
9474
9475TEST_F_WITH_FLAGS(
9476 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
9477 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9478 rate_limit_user_activity_poke_in_dispatcher))) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009479 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009480 milliseconds_to_nanoseconds(200));
9481 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009482 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
9483 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009484
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009485 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009486 milliseconds_to_nanoseconds(280));
9487 mFakePolicy->assertUserActivityNotPoked();
9488
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009489 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009490 milliseconds_to_nanoseconds(340));
9491 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009492 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
9493 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009494}
9495
9496TEST_F_WITH_FLAGS(
9497 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
9498 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9499 rate_limit_user_activity_poke_in_dispatcher))) {
9500 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
9501
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009502 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9503 20);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009504 mFakePolicy->assertUserActivityPoked();
9505
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009506 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9507 30);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009508 mFakePolicy->assertUserActivityPoked();
9509}
9510
chaviwfd6d3512019-03-25 13:23:49 -07009511class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009512 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07009513 InputDispatcherTest::SetUp();
9514
Chris Yea209fde2020-07-22 13:54:51 -07009515 std::shared_ptr<FakeApplicationHandle> application =
9516 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009517 mUnfocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
9518 ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009519 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07009520
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009521 mFocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
9522 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009523 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07009524
9525 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009526 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07009527 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07009528
9529 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009530 mDispatcher->onWindowInfosChanged(
9531 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009532 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009533 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07009534 }
9535
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009536 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07009537 InputDispatcherTest::TearDown();
9538
9539 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009540 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07009541 }
9542
9543protected:
9544 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009545 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07009546 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07009547};
9548
9549// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9550// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
9551// the onPointerDownOutsideFocus callback.
9552TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009554 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9555 ui::LogicalDisplayId::DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009556 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009557 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009558
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009559 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07009560 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
9561}
9562
9563// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
9564// DOWN on the window that doesn't have focus. Ensure no window received the
9565// onPointerDownOutsideFocus callback.
9566TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009568 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009569 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009570 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009571 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009572
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009573 ASSERT_TRUE(mDispatcher->waitForIdle());
9574 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009575}
9576
9577// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
9578// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
9579TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08009580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009581 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009582 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009583 mFocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009584
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009585 ASSERT_TRUE(mDispatcher->waitForIdle());
9586 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009587}
9588
9589// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9590// DOWN on the window that already has focus. Ensure no window received the
9591// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009592TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009593 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009594 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9595 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009596 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009597 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009598
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009599 ASSERT_TRUE(mDispatcher->waitForIdle());
9600 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009601}
9602
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009603// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
9604// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
9605TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
9606 const MotionEvent event =
9607 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
9608 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009609 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009610 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
9611 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009612 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009613 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009614 mUnfocusedWindow->consumeAnyMotionDown(ui::LogicalDisplayId::DEFAULT,
9615 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009616
9617 ASSERT_TRUE(mDispatcher->waitForIdle());
9618 mFakePolicy->assertOnPointerDownWasNotCalled();
9619 // Ensure that the unfocused window did not receive any FOCUS events.
9620 mUnfocusedWindow->assertNoEvents();
9621}
9622
chaviwaf87b3e2019-10-01 16:59:28 -07009623// These tests ensures we can send touch events to a single client when there are multiple input
9624// windows that point to the same client token.
9625class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
9626 virtual void SetUp() override {
9627 InputDispatcherTest::SetUp();
9628
Chris Yea209fde2020-07-22 13:54:51 -07009629 std::shared_ptr<FakeApplicationHandle> application =
9630 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009631 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009632 ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009633 mWindow1->setFrame(Rect(0, 0, 100, 100));
9634
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009635 mWindow2 = mWindow1->clone(ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009636 mWindow2->setFrame(Rect(100, 100, 200, 200));
9637
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009638 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009639 }
9640
9641protected:
9642 sp<FakeWindowHandle> mWindow1;
9643 sp<FakeWindowHandle> mWindow2;
9644
9645 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05009646 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07009647 vec2 vals = windowInfo->transform.transform(point.x, point.y);
9648 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07009649 }
9650
9651 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
9652 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009653 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009654 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009655 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009656 ASSERT_NE(nullptr, motionEvent);
9657 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07009658
9659 for (size_t i = 0; i < points.size(); i++) {
9660 float expectedX = points[i].x;
9661 float expectedY = points[i].y;
9662
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009663 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009664 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009665 << ", got " << motionEvent->getX(i);
9666 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009667 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009668 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07009669 }
9670 }
chaviw9eaa22c2020-07-01 16:21:27 -07009671
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009672 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
9673 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07009674 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009675 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009676 ui::LogicalDisplayId::DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07009677
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009678 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009679 }
chaviwaf87b3e2019-10-01 16:59:28 -07009680};
9681
9682TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
9683 // Touch Window 1
9684 PointF touchedPoint = {10, 10};
9685 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009686 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009687
9688 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009689 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009690
9691 // Touch Window 2
9692 touchedPoint = {150, 150};
9693 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009694 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009695}
9696
chaviw9eaa22c2020-07-01 16:21:27 -07009697TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
9698 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07009699 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009700 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009701
9702 // Touch Window 1
9703 PointF touchedPoint = {10, 10};
9704 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009705 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009706 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009707 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009708
9709 // Touch Window 2
9710 touchedPoint = {150, 150};
9711 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009712 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
9713 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009714
chaviw9eaa22c2020-07-01 16:21:27 -07009715 // Update the transform so rotation is set
9716 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009717 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009718 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009719 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009720}
9721
chaviw9eaa22c2020-07-01 16:21:27 -07009722TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009723 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009724 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009725
9726 // Touch Window 1
9727 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9728 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009729 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009730
9731 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009732 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
9733 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
9734 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07009735 touchedPoints.push_back(PointF{150, 150});
9736 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009737 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009738
chaviw9eaa22c2020-07-01 16:21:27 -07009739 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009740 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009741 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009742
chaviw9eaa22c2020-07-01 16:21:27 -07009743 // Update the transform so rotation is set for Window 2
9744 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009745 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009746 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009747 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009748}
9749
chaviw9eaa22c2020-07-01 16:21:27 -07009750TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009751 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009752 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009753
9754 // Touch Window 1
9755 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9756 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009757 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009758
9759 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009760 touchedPoints.push_back(PointF{150, 150});
9761 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009762
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009763 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009764
9765 // Move both windows
9766 touchedPoints = {{20, 20}, {175, 175}};
9767 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9768 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9769
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009770 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009771
chaviw9eaa22c2020-07-01 16:21:27 -07009772 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009773 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009774 expectedPoints.pop_back();
9775
9776 // Touch Window 2
9777 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009778 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009779 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009780 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009781
9782 // Move both windows
9783 touchedPoints = {{20, 20}, {175, 175}};
9784 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9785 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9786
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009787 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009788}
9789
9790TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
9791 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009792 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009793
9794 // Touch Window 1
9795 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9796 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009797 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009798
9799 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009800 touchedPoints.push_back(PointF{150, 150});
9801 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009802
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009803 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009804
9805 // Move both windows
9806 touchedPoints = {{20, 20}, {175, 175}};
9807 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9808 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9809
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009810 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009811}
9812
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009813/**
9814 * When one of the windows is slippery, the touch should not slip into the other window with the
9815 * same input channel.
9816 */
9817TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
9818 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009819 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009820
9821 // Touch down in window 1
9822 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009823 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009824 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
9825
9826 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
9827 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
9828 // getting generated.
9829 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009830 ui::LogicalDisplayId::DEFAULT, {{150, 150}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009831
9832 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
9833}
9834
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009835/**
9836 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
9837 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
9838 * that the pointer is hovering over may have a different transform.
9839 */
9840TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009841 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009842
9843 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009844 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
9845 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9846 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009847 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
9848 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009849 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009850 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9851 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9852 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009853 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009854 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009855 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
9856}
9857
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009858class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
9859 virtual void SetUp() override {
9860 InputDispatcherTest::SetUp();
9861
Chris Yea209fde2020-07-22 13:54:51 -07009862 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009863 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009864 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009865 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009866 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009867 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07009868 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009869
9870 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009871 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009872
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009873 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009874 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009875 mWindow->consumeFocusEvent(true);
9876 }
9877
9878 virtual void TearDown() override {
9879 InputDispatcherTest::TearDown();
9880 mWindow.clear();
9881 }
9882
9883protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009884 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07009885 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009886 sp<FakeWindowHandle> mWindow;
9887 static constexpr PointF WINDOW_LOCATION = {20, 20};
9888
9889 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009890 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
9891 .x(WINDOW_LOCATION.x)
9892 .y(WINDOW_LOCATION.y);
9893 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9894 .pointer(touchingPointer)
9895 .build());
9896 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9897 .pointer(touchingPointer)
9898 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009899 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009900
9901 sp<FakeWindowHandle> addSpyWindow() {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009902 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy",
9903 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009904 spy->setTrustedOverlay(true);
9905 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009906 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009907 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009908 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009909 return spy;
9910 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009911};
9912
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009913// Send a tap and respond, which should not cause an ANR.
9914TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
9915 tapOnWindow();
9916 mWindow->consumeMotionDown();
9917 mWindow->consumeMotionUp();
9918 ASSERT_TRUE(mDispatcher->waitForIdle());
9919 mFakePolicy->assertNotifyAnrWasNotCalled();
9920}
9921
9922// Send a regular key and respond, which should not cause an ANR.
9923TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009924 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009925 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009926 ASSERT_TRUE(mDispatcher->waitForIdle());
9927 mFakePolicy->assertNotifyAnrWasNotCalled();
9928}
9929
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009930TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
9931 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009932 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009933 mWindow->consumeFocusEvent(false);
9934
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009935 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009936 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9937 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
9938 CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00009939 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009941 // Key will not go to window because we have no focused window.
9942 // The 'no focused window' ANR timer should start instead.
9943
9944 // Now, the focused application goes away.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009945 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, nullptr);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009946 // The key should get dropped and there should be no ANR.
9947
9948 ASSERT_TRUE(mDispatcher->waitForIdle());
9949 mFakePolicy->assertNotifyAnrWasNotCalled();
9950}
9951
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009952// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009953// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9954// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009955TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009957 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9958 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009959
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009960 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009961 ASSERT_TRUE(sequenceNum);
9962 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009963 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009964
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009965 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009966 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009967 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009968 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009969 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009970}
9971
9972// Send a key to the app and have the app not respond right away.
9973TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
9974 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009975 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009976 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009977 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009978 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009979 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009980 ASSERT_TRUE(mDispatcher->waitForIdle());
9981}
9982
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009983// We have a focused application, but no focused window
9984TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07009985 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009986 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009987 mWindow->consumeFocusEvent(false);
9988
9989 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009991 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9992 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009993 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9994 mDispatcher->waitForIdle();
9995 mFakePolicy->assertNotifyAnrWasNotCalled();
9996
9997 // Once a focused event arrives, we get an ANR for this application
9998 // We specify the injection timeout to be smaller than the application timeout, to ensure that
9999 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010000 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010001 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10002 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT, 50ms,
Linnan Li13bf76a2024-05-05 19:18:02 +080010003 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010004 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010005 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -070010006 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010007 ASSERT_TRUE(mDispatcher->waitForIdle());
10008}
10009
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010010/**
10011 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
10012 * there will not be an ANR.
10013 */
10014TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
10015 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010016 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010017 mWindow->consumeFocusEvent(false);
10018
10019 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -070010020 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
10021 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010022 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
10023 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
10024
10025 // Define a valid key down event that is stale (too old).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010026 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
10027 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN,
10028 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime,
10029 eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010030
Hu Guofe3c8f12023-09-22 17:20:15 +080010031 const int32_t policyFlags =
10032 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010033
10034 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +000010035 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010036 InputEventInjectionSync::WAIT_FOR_RESULT,
10037 INJECT_EVENT_TIMEOUT, policyFlags);
10038 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
10039 << "Injection should fail because the event is stale";
10040
10041 ASSERT_TRUE(mDispatcher->waitForIdle());
10042 mFakePolicy->assertNotifyAnrWasNotCalled();
10043 mWindow->assertNoEvents();
10044}
10045
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010046// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010047// Make sure that we don't notify policy twice about the same ANR.
10048TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010049 const std::chrono::duration appTimeout = 400ms;
10050 mApplication->setDispatchingTimeout(appTimeout);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010051 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010052
Vishnu Nair47074b82020-08-14 11:54:47 -070010053 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010054 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010055 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010056
10057 // Once a focused event arrives, we get an ANR for this application
10058 // We specify the injection timeout to be smaller than the application timeout, to ensure that
10059 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010060 const std::chrono::duration eventInjectionTimeout = 100ms;
10061 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010062 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010063 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10064 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT,
10065 eventInjectionTimeout,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010066 /*allowKeyRepeat=*/false);
10067 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
10068 << "result=" << ftl::enum_string(result);
10069 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
10070 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
10071 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
10072 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010073
Vishnu Naire4df8752022-09-08 09:17:55 -070010074 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010075 // ANR should not be raised again. It is up to policy to do that if it desires.
10076 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010077
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010078 // If we now get a focused window, the ANR should stop, but the policy handles that via
10079 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010080 ASSERT_TRUE(mDispatcher->waitForIdle());
10081}
10082
10083// We have a focused application, but no focused window
10084TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -070010085 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010086 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010087 mWindow->consumeFocusEvent(false);
10088
10089 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010090 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010091
Vishnu Naire4df8752022-09-08 09:17:55 -070010092 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10093 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010094
10095 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010096 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010097 ASSERT_TRUE(mDispatcher->waitForIdle());
10098 mWindow->assertNoEvents();
10099}
10100
10101/**
10102 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
10103 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
10104 * If we process 1 of the events, but ANR on the second event with the same timestamp,
10105 * the ANR mechanism should still work.
10106 *
10107 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
10108 * DOWN event, while not responding on the second one.
10109 */
10110TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
10111 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010112 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010113 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010114 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10115 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010116 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010117
10118 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010119 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010120 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010121 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10122 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010123 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010124
10125 // 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 -070010126 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010127 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010128 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010129}
10130
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010131// A spy window can receive an ANR
10132TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
10133 sp<FakeWindowHandle> spy = addSpyWindow();
10134
10135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010136 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10137 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010138 mWindow->consumeMotionDown();
10139
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010140 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010141 ASSERT_TRUE(sequenceNum);
10142 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010143 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010144
10145 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010146 spy->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010147 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010148 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010149 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010150}
10151
10152// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010153// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010154TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
10155 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010156
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010158 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
10159 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
10160 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10161 injectKeyUp(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010162
10163 // Stuck on the ACTION_UP
10164 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010165 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010166
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010167 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010168 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010169 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10170 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010171
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010172 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010173 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010174 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010175 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010176 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010177}
10178
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010179// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010180// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010181TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
10182 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010183
10184 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010185 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10186 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010187
10188 mWindow->consumeMotionDown();
10189 // Stuck on the ACTION_UP
10190 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010191 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010192
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010193 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010194 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010195 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10196 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010197
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010198 mWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010199 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010200 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010201 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010202 spy->assertNoEvents();
10203}
10204
10205TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010206 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010207
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010208 FakeMonitorReceiver monitor =
10209 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010210
10211 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010212 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10213 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010214
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010215 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010216 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
10217 ASSERT_TRUE(consumeSeq);
10218
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010219 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
10220 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010221
10222 monitor.finishEvent(*consumeSeq);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010223 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010224
10225 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010226 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010227}
10228
10229// If a window is unresponsive, then you get anr. if the window later catches up and starts to
10230// process events, you don't get an anr. When the window later becomes unresponsive again, you
10231// get an ANR again.
10232// 1. tap -> block on ACTION_UP -> receive ANR
10233// 2. consume all pending events (= queue becomes healthy again)
10234// 3. tap again -> block on ACTION_UP again -> receive ANR second time
10235TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
10236 tapOnWindow();
10237
10238 mWindow->consumeMotionDown();
10239 // Block on ACTION_UP
10240 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010241 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010242 mWindow->consumeMotionUp(); // Now the connection should be healthy again
10243 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010244 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010245 mWindow->assertNoEvents();
10246
10247 tapOnWindow();
10248 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010249 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010250 mWindow->consumeMotionUp();
10251
10252 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010253 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010254 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010255 mWindow->assertNoEvents();
10256}
10257
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010258// If a connection remains unresponsive for a while, make sure policy is only notified once about
10259// it.
10260TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010262 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10263 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010264
10265 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010266 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010267 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010268 // 'notifyConnectionUnresponsive' should only be called once per connection
10269 mFakePolicy->assertNotifyAnrWasNotCalled();
10270 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010271 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010272 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010273 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010274 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010275 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010276 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010277 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010278}
10279
10280/**
10281 * 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 -070010282 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010283 */
10284TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010285 // The timeouts in this test are established by relying on the fact that the "key waiting for
10286 // events timeout" is equal to 500ms.
10287 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010288 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010289 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010290
10291 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010292 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010293 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010294 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010295 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010296
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010297 // Don't finish the events yet, and send a key
10298 mDispatcher->notifyKey(
10299 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10300 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10301 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010302 // Key will not be sent to the window, yet, because the window is still processing events
10303 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010304 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010305 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010306
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010307 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010308 // if we wait long enough though, dispatcher will give up, and still send the key
10309 // to the focused window, even though we have not yet finished the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010310 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010311 mWindow->finishEvent(*downSequenceNum);
10312 mWindow->finishEvent(*upSequenceNum);
10313}
10314
10315/**
10316 * If a window is processing a motion event, and then a key event comes in, the key event should
10317 * not go to the focused window until the motion is processed.
10318 * If then a new motion comes in, then the pending key event should be going to the currently
10319 * focused window right away.
10320 */
10321TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010322 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
10323 // The timeouts in this test are established by relying on the fact that the "key waiting for
10324 // events timeout" is equal to 500ms.
10325 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010326 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010327 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010328
10329 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010330 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010331 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010332 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010333 ASSERT_TRUE(upSequenceNum);
10334 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010335 mDispatcher->notifyKey(
10336 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10337 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10338 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010339 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010340 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010341
10342 // Now tap down again. It should cause the pending key to go to the focused window right away.
10343 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010344 // Now that we tapped, we should receive the key immediately.
10345 // Since there's still room for slowness, we use 200ms, which is much less than
10346 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
10347 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
10348 ASSERT_NE(nullptr, keyEvent);
10349 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
10350 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
10351 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
10352 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010353 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
10354 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010355 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10356 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010357 mWindow->assertNoEvents();
10358}
10359
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010360/**
10361 * Send an event to the app and have the app not respond right away.
10362 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10363 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
10364 * At some point, the window becomes responsive again.
10365 * Ensure that subsequent events get dropped, and the next gesture is delivered.
10366 */
10367TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
10368 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10369 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
10370 .build());
10371
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010372 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010373 ASSERT_TRUE(sequenceNum);
10374 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10375 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10376
10377 mWindow->finishEvent(*sequenceNum);
10378 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
10379 ASSERT_TRUE(mDispatcher->waitForIdle());
10380 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10381
10382 // Now that the window is responsive, let's continue the gesture.
10383 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10384 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10385 .build());
10386
10387 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10388 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10389 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10390 .build());
10391
10392 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10393 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10394 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10395 .build());
10396 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10397 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10398 .build());
10399 // We already canceled this pointer, so the window shouldn't get any new events.
10400 mWindow->assertNoEvents();
10401
10402 // Start another one.
10403 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10404 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
10405 .build());
10406 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10407}
10408
Prabir Pradhanfc364722024-02-08 17:51:20 +000010409// Send an event to the app and have the app not respond right away. Then remove the app window.
10410// When the window is removed, the dispatcher will cancel the events for that window.
10411// So InputDispatcher will enqueue ACTION_CANCEL event as well.
10412TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
10413 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010414 AINPUT_SOURCE_TOUCHSCREEN,
10415 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010416
10417 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10418 ASSERT_TRUE(sequenceNum);
10419
10420 // Remove the window, but the input channel should remain alive.
10421 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10422
10423 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10424 // Since the window was removed, Dispatcher does not know the PID associated with the window
10425 // anymore, so the policy is notified without the PID.
10426 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
10427 /*pid=*/std::nullopt);
10428
10429 mWindow->finishEvent(*sequenceNum);
10430 // The cancellation was generated when the window was removed, along with the focus event.
10431 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010432 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010433 mWindow->consumeFocusEvent(false);
10434 ASSERT_TRUE(mDispatcher->waitForIdle());
10435 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10436}
10437
10438// Send an event to the app and have the app not respond right away. Wait for the policy to be
10439// notified of the unresponsive window, then remove the app window.
10440TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
10441 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010442 AINPUT_SOURCE_TOUCHSCREEN,
10443 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010444
10445 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10446 ASSERT_TRUE(sequenceNum);
10447 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10448 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10449
10450 // Remove the window, but the input channel should remain alive.
10451 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10452
10453 mWindow->finishEvent(*sequenceNum);
10454 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
10455 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010456 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010457 mWindow->consumeFocusEvent(false);
10458 ASSERT_TRUE(mDispatcher->waitForIdle());
10459 // Since the window was removed, Dispatcher does not know the PID associated with the window
10460 // becoming responsive, so the policy is notified without the PID.
10461 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10462}
10463
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010464class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
10465 virtual void SetUp() override {
10466 InputDispatcherTest::SetUp();
10467
Chris Yea209fde2020-07-22 13:54:51 -070010468 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010469 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010470 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010471 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010472 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010473 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010474 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010475
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010476 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010477 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010478 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010479 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010480
10481 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010482 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -070010483 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010484
10485 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010486 mDispatcher->onWindowInfosChanged(
10487 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010488 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010489 mFocusedWindow->consumeFocusEvent(true);
10490 }
10491
10492 virtual void TearDown() override {
10493 InputDispatcherTest::TearDown();
10494
10495 mUnfocusedWindow.clear();
10496 mFocusedWindow.clear();
10497 }
10498
10499protected:
Chris Yea209fde2020-07-22 13:54:51 -070010500 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010501 sp<FakeWindowHandle> mUnfocusedWindow;
10502 sp<FakeWindowHandle> mFocusedWindow;
10503 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
10504 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
10505 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
10506
10507 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
10508
10509 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
10510
10511private:
10512 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010513 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010514 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10515 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010516 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010517 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10518 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010519 }
10520};
10521
10522// If we have 2 windows that are both unresponsive, the one with the shortest timeout
10523// should be ANR'd first.
10524TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010525 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010526 injectMotionEvent(*mDispatcher,
10527 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10528 AINPUT_SOURCE_TOUCHSCREEN)
10529 .pointer(PointerBuilder(0, ToolType::FINGER)
10530 .x(FOCUSED_WINDOW_LOCATION.x)
10531 .y(FOCUSED_WINDOW_LOCATION.y))
10532 .build()));
10533 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10534 injectMotionEvent(*mDispatcher,
10535 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
10536 AINPUT_SOURCE_TOUCHSCREEN)
10537 .pointer(PointerBuilder(0, ToolType::FINGER)
10538 .x(FOCUSED_WINDOW_LOCATION.x)
10539 .y(FOCUSED_WINDOW_LOCATION.y))
10540 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010541 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010542 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010543 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010544 // We consumed all events, so no ANR
10545 ASSERT_TRUE(mDispatcher->waitForIdle());
10546 mFakePolicy->assertNotifyAnrWasNotCalled();
10547
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010549 injectMotionEvent(*mDispatcher,
10550 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10551 AINPUT_SOURCE_TOUCHSCREEN)
10552 .pointer(PointerBuilder(0, ToolType::FINGER)
10553 .x(FOCUSED_WINDOW_LOCATION.x)
10554 .y(FOCUSED_WINDOW_LOCATION.y))
10555 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010556 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010557 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010558
10559 const std::chrono::duration timeout =
10560 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010561 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010562
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010563 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010564 mFocusedWindow->consumeMotionDown();
10565 // This cancel is generated because the connection was unresponsive
10566 mFocusedWindow->consumeMotionCancel();
10567 mFocusedWindow->assertNoEvents();
10568 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010569 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010570 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10571 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010572 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010573}
10574
10575// If we have 2 windows with identical timeouts that are both unresponsive,
10576// it doesn't matter which order they should have ANR.
10577// But we should receive ANR for both.
10578TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
10579 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010580 mUnfocusedWindow->setDispatchingTimeout(
10581 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010582 mDispatcher->onWindowInfosChanged(
10583 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010584
10585 tapOnFocusedWindow();
10586 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010587 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010588 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
10589 mFocusedWindow->getDispatchingTimeout(
10590 DISPATCHING_TIMEOUT)),
10591 mFakePolicy->getUnresponsiveWindowToken(0ms)};
10592
10593 ASSERT_THAT(anrConnectionTokens,
10594 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10595 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010596
10597 ASSERT_TRUE(mDispatcher->waitForIdle());
10598 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010599
10600 mFocusedWindow->consumeMotionDown();
10601 mFocusedWindow->consumeMotionUp();
10602 mUnfocusedWindow->consumeMotionOutside();
10603
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010604 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
10605 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010606
10607 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010608 ASSERT_THAT(responsiveTokens,
10609 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10610 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010611 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010612}
10613
10614// If a window is already not responding, the second tap on the same window should be ignored.
10615// We should also log an error to account for the dropped event (not tested here).
10616// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
10617TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
10618 tapOnFocusedWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010619 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010620 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010621 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010622 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010623 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010624 ASSERT_TRUE(upEventSequenceNum);
10625 const std::chrono::duration timeout =
10626 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010627 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010628
10629 // Tap once again
10630 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010631 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010632 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10633 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010634 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010635 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010636 FOCUSED_WINDOW_LOCATION));
10637 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
10638 // valid touch target
10639 mUnfocusedWindow->assertNoEvents();
10640
10641 // Consume the first tap
10642 mFocusedWindow->finishEvent(*downEventSequenceNum);
10643 mFocusedWindow->finishEvent(*upEventSequenceNum);
10644 ASSERT_TRUE(mDispatcher->waitForIdle());
10645 // The second tap did not go to the focused window
10646 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010647 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -080010648 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10649 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010650 mFakePolicy->assertNotifyAnrWasNotCalled();
10651}
10652
10653// If you tap outside of all windows, there will not be ANR
10654TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010655 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010656 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10657 ui::LogicalDisplayId::DEFAULT, LOCATION_OUTSIDE_ALL_WINDOWS));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010658 ASSERT_TRUE(mDispatcher->waitForIdle());
10659 mFakePolicy->assertNotifyAnrWasNotCalled();
10660}
10661
10662// Since the focused window is paused, tapping on it should not produce any events
10663TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
10664 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010665 mDispatcher->onWindowInfosChanged(
10666 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010667
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010668 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010669 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10670 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010671
10672 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
10673 ASSERT_TRUE(mDispatcher->waitForIdle());
10674 // Should not ANR because the window is paused, and touches shouldn't go to it
10675 mFakePolicy->assertNotifyAnrWasNotCalled();
10676
10677 mFocusedWindow->assertNoEvents();
10678 mUnfocusedWindow->assertNoEvents();
10679}
10680
10681/**
10682 * 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 -070010683 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010684 * If a different window becomes focused at this time, the key should go to that window instead.
10685 *
10686 * Warning!!!
10687 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
10688 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010689 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010690 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
10691 *
10692 * If that value changes, this test should also change.
10693 */
10694TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
10695 // Set a long ANR timeout to prevent it from triggering
10696 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010697 mDispatcher->onWindowInfosChanged(
10698 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010699
10700 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010701 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010702 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010703 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010704 ASSERT_TRUE(upSequenceNum);
10705 // Don't finish the events yet, and send a key
10706 // Injection will succeed because we will eventually give up and send the key to the focused
10707 // window even if motions are still being processed.
10708
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010709 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010710 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10711 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010712 /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010714 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010715 // and the key remains pending, waiting for the touch events to be processed.
10716 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
10717 // under the hood.
10718 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
10719 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010720
10721 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -070010722 mFocusedWindow->setFocusable(false);
10723 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010724 mDispatcher->onWindowInfosChanged(
10725 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010726 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010727
10728 // Focus events should precede the key events
10729 mUnfocusedWindow->consumeFocusEvent(true);
10730 mFocusedWindow->consumeFocusEvent(false);
10731
10732 // Finish the tap events, which should unblock dispatcher
10733 mUnfocusedWindow->finishEvent(*downSequenceNum);
10734 mUnfocusedWindow->finishEvent(*upSequenceNum);
10735
10736 // Now that all queues are cleared and no backlog in the connections, the key event
10737 // can finally go to the newly focused "mUnfocusedWindow".
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010738 mUnfocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010739 mFocusedWindow->assertNoEvents();
10740 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010741 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010742}
10743
10744// When the touch stream is split across 2 windows, and one of them does not respond,
10745// then ANR should be raised and the touch should be canceled for the unresponsive window.
10746// The other window should not be affected by that.
10747TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
10748 // Touch Window 1
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010749 mDispatcher->notifyMotion(
10750 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10751 ui::LogicalDisplayId::DEFAULT, {FOCUSED_WINDOW_LOCATION}));
10752 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010753
10754 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +000010755 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010756 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10757 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010758 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010759
10760 const std::chrono::duration timeout =
10761 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010762 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010763
10764 mUnfocusedWindow->consumeMotionDown();
10765 mFocusedWindow->consumeMotionDown();
10766 // Focused window may or may not receive ACTION_MOVE
10767 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010768 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010769 ASSERT_TRUE(moveOrCancelSequenceNum);
10770 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
10771 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -070010772 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010773 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
10774 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
10775 mFocusedWindow->consumeMotionCancel();
10776 } else {
10777 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
10778 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010779 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010780 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10781 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010782
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010783 mUnfocusedWindow->assertNoEvents();
10784 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010785 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010786}
10787
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010788/**
10789 * If we have no focused window, and a key comes in, we start the ANR timer.
10790 * The focused application should add a focused window before the timer runs out to prevent ANR.
10791 *
10792 * If the user touches another application during this time, the key should be dropped.
10793 * Next, if a new focused window comes in, without toggling the focused application,
10794 * then no ANR should occur.
10795 *
10796 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
10797 * but in some cases the policy may not update the focused application.
10798 */
10799TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
10800 std::shared_ptr<FakeApplicationHandle> focusedApplication =
10801 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -070010802 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010803 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, focusedApplication);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010804 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
10805 mFocusedWindow->setFocusable(false);
10806
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010807 mDispatcher->onWindowInfosChanged(
10808 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010809 mFocusedWindow->consumeFocusEvent(false);
10810
10811 // Send a key. The ANR timer should start because there is no focused window.
10812 // 'focusedApplication' will get blamed if this timer completes.
10813 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010814 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010815 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10816 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010817 /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +000010818 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010819 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010820
10821 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
10822 // then the injected touches won't cause the focused event to get dropped.
10823 // The dispatcher only checks for whether the queue should be pruned upon queueing.
10824 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
10825 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
10826 // For this test, it means that the key would get delivered to the window once it becomes
10827 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010828 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010829
10830 // Touch unfocused window. This should force the pending key to get dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010831 mDispatcher->notifyMotion(
10832 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10833 ui::LogicalDisplayId::DEFAULT, {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010834
10835 // We do not consume the motion right away, because that would require dispatcher to first
10836 // process (== drop) the key event, and by that time, ANR will be raised.
10837 // Set the focused window first.
10838 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010839 mDispatcher->onWindowInfosChanged(
10840 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010841 setFocusedWindow(mFocusedWindow);
10842 mFocusedWindow->consumeFocusEvent(true);
10843 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
10844 // to another application. This could be a bug / behaviour in the policy.
10845
10846 mUnfocusedWindow->consumeMotionDown();
10847
10848 ASSERT_TRUE(mDispatcher->waitForIdle());
10849 // Should not ANR because we actually have a focused window. It was just added too slowly.
10850 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
10851}
10852
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010853/**
10854 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
10855 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
10856 * dispatcher doesn't prune pointer events incorrectly.
10857 *
10858 * This test reproduces a crash in InputDispatcher.
10859 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
10860 *
10861 * Keep the currently focused application (mApplication), and have no focused window.
10862 * We set up two additional windows:
10863 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
10864 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
10865 * window. This window is not focusable, but is touchable.
10866 *
10867 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
10868 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
10869 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
10870 *
10871 * Now, we touch "Another window". This window is owned by a different application than
10872 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
10873 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
10874 * dropping the events from its queue. Ensure that no crash occurs.
10875 *
10876 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
10877 * This does not affect the test running time.
10878 */
10879TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
10880 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
10881 std::make_shared<FakeApplicationHandle>();
10882 systemUiApplication->setDispatchingTimeout(3000ms);
10883 mFakePolicy->setStaleEventTimeout(3000ms);
10884 sp<FakeWindowHandle> navigationBar =
10885 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010886 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010887 navigationBar->setFocusable(false);
10888 navigationBar->setWatchOutsideTouch(true);
10889 navigationBar->setFrame(Rect(0, 0, 100, 100));
10890
10891 mApplication->setDispatchingTimeout(3000ms);
10892 // 'mApplication' is already focused, but we call it again here to make it explicit.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010893 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010894
10895 std::shared_ptr<FakeApplicationHandle> anotherApplication =
10896 std::make_shared<FakeApplicationHandle>();
10897 sp<FakeWindowHandle> appWindow =
10898 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010899 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010900 appWindow->setFocusable(false);
10901 appWindow->setFrame(Rect(100, 100, 200, 200));
10902
10903 mDispatcher->onWindowInfosChanged(
10904 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
10905 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
10906 mFocusedWindow->consumeFocusEvent(false);
10907
10908 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
10909 // in response.
10910 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10911 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10912 .build());
10913 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10914
10915 // Key will not be sent anywhere because we have no focused window. It will remain pending.
10916 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
10917 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010918 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10919 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010920 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010921 /*allowKeyRepeat=*/false);
10922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10923
10924 // Finish the gesture - lift up finger and inject ACTION_UP key event
10925 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10926 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10927 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010928 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0,
10929 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010930 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010931 /*allowKeyRepeat=*/false);
10932 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10933 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
10934 // getting any events yet.
10935 navigationBar->assertNoEvents();
10936
10937 // Now touch "Another window". This touch is going to a different application than the one we
10938 // are waiting for (which is 'mApplication').
10939 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
10940 // trying to be injected) and to continue processing the rest of the events in the original
10941 // order.
10942 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10943 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
10944 .build());
10945 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
10946 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
10947 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10948
10949 appWindow->assertNoEvents();
10950 navigationBar->assertNoEvents();
10951}
10952
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010953// These tests ensure we cannot send touch events to a window that's positioned behind a window
10954// that has feature NO_INPUT_CHANNEL.
10955// Layout:
10956// Top (closest to user)
10957// mNoInputWindow (above all windows)
10958// mBottomWindow
10959// Bottom (furthest from user)
10960class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
10961 virtual void SetUp() override {
10962 InputDispatcherTest::SetUp();
10963
10964 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010965 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
10966 "Window without input channel",
10967 ui::LogicalDisplayId::DEFAULT,
10968 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010969 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010970 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
10971 // It's perfectly valid for this window to not have an associated input channel
10972
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010973 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010974 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010975 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
10976
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010977 mDispatcher->onWindowInfosChanged(
10978 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010979 }
10980
10981protected:
10982 std::shared_ptr<FakeApplicationHandle> mApplication;
10983 sp<FakeWindowHandle> mNoInputWindow;
10984 sp<FakeWindowHandle> mBottomWindow;
10985};
10986
10987TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
10988 PointF touchedPoint = {10, 10};
10989
Prabir Pradhan678438e2023-04-13 19:32:51 +000010990 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010991 AINPUT_SOURCE_TOUCHSCREEN,
10992 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010993
10994 mNoInputWindow->assertNoEvents();
10995 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
10996 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
10997 // and therefore should prevent mBottomWindow from receiving touches
10998 mBottomWindow->assertNoEvents();
10999}
11000
11001/**
11002 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
11003 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
11004 */
11005TEST_F(InputDispatcherMultiWindowOcclusionTests,
11006 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011007 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
11008 "Window with input channel and NO_INPUT_CHANNEL",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011009 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011010
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011011 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011012 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011013 mDispatcher->onWindowInfosChanged(
11014 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011015
11016 PointF touchedPoint = {10, 10};
11017
Prabir Pradhan678438e2023-04-13 19:32:51 +000011018 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011019 AINPUT_SOURCE_TOUCHSCREEN,
11020 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011021
11022 mNoInputWindow->assertNoEvents();
11023 mBottomWindow->assertNoEvents();
11024}
11025
Vishnu Nair958da932020-08-21 17:12:37 -070011026class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
11027protected:
11028 std::shared_ptr<FakeApplicationHandle> mApp;
11029 sp<FakeWindowHandle> mWindow;
11030 sp<FakeWindowHandle> mMirror;
11031
11032 virtual void SetUp() override {
11033 InputDispatcherTest::SetUp();
11034 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011035 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11036 ui::LogicalDisplayId::DEFAULT);
11037 mMirror = mWindow->clone(ui::LogicalDisplayId::DEFAULT);
11038 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Vishnu Nair958da932020-08-21 17:12:37 -070011039 mWindow->setFocusable(true);
11040 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011041 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011042 }
11043};
11044
11045TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
11046 // Request focus on a mirrored window
11047 setFocusedWindow(mMirror);
11048
11049 // window gets focused
11050 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011051 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011052 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011053 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011054}
11055
11056// A focused & mirrored window remains focused only if the window and its mirror are both
11057// focusable.
11058TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
11059 setFocusedWindow(mMirror);
11060
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000011061 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -070011062 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011063 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011064 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011065 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011067 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011068 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011069
11070 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011071 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011072
11073 // window loses focus since one of the windows associated with the token in not focusable
11074 mWindow->consumeFocusEvent(false);
11075
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011076 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011077 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011078 mWindow->assertNoEvents();
11079}
11080
11081// A focused & mirrored window remains focused until the window and its mirror both become
11082// invisible.
11083TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
11084 setFocusedWindow(mMirror);
11085
11086 // window gets focused
11087 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011089 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011090 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011092 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011093 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011094
11095 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011096 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011097
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011098 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011099 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011100 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011101 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011102 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011103 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011104
11105 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011106 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011107
11108 // window loses focus only after all windows associated with the token become invisible.
11109 mWindow->consumeFocusEvent(false);
11110
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011111 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011112 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011113 mWindow->assertNoEvents();
11114}
11115
11116// A focused & mirrored window remains focused until both windows are removed.
11117TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
11118 setFocusedWindow(mMirror);
11119
11120 // window gets focused
11121 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011122 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011123 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011124 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011125 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011126 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011127 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011128
11129 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011130 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011131
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011133 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011134 mMirror->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011135 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011136 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011137 mMirror->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011138
11139 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011140 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011141 mWindow->consumeFocusEvent(false);
11142
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011143 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011144 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011145 mWindow->assertNoEvents();
11146}
11147
11148// Focus request can be pending until one window becomes visible.
11149TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
11150 // Request focus on an invisible mirror.
11151 mWindow->setVisible(false);
11152 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011153 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011154 setFocusedWindow(mMirror);
11155
11156 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011158 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011159 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -070011160
11161 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011162 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011163
11164 // window gets focused
11165 mWindow->consumeFocusEvent(true);
11166 // window gets the pending key event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011167 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -070011168}
Prabir Pradhan99987712020-11-10 18:43:05 -080011169
11170class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
11171protected:
11172 std::shared_ptr<FakeApplicationHandle> mApp;
11173 sp<FakeWindowHandle> mWindow;
11174 sp<FakeWindowHandle> mSecondWindow;
11175
11176 void SetUp() override {
11177 InputDispatcherTest::SetUp();
11178 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011179 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11180 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080011181 mWindow->setFocusable(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011182 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11183 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080011184 mSecondWindow->setFocusable(true);
11185
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011186 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011187 mDispatcher->onWindowInfosChanged(
11188 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -080011189
11190 setFocusedWindow(mWindow);
11191 mWindow->consumeFocusEvent(true);
11192 }
11193
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011194 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011195 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -080011196 }
11197
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011198 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
11199 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -080011200 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +090011201 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011202 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011203 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011204 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -080011205 }
11206};
11207
11208TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
11209 // Ensure that capture cannot be obtained for unfocused windows.
11210 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11211 mFakePolicy->assertSetPointerCaptureNotCalled();
11212 mSecondWindow->assertNoEvents();
11213
11214 // Ensure that capture can be enabled from the focus window.
11215 requestAndVerifyPointerCapture(mWindow, true);
11216
11217 // Ensure that capture cannot be disabled from a window that does not have capture.
11218 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
11219 mFakePolicy->assertSetPointerCaptureNotCalled();
11220
11221 // Ensure that capture can be disabled from the window with capture.
11222 requestAndVerifyPointerCapture(mWindow, false);
11223}
11224
11225TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011226 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011227
11228 setFocusedWindow(mSecondWindow);
11229
11230 // Ensure that the capture disabled event was sent first.
11231 mWindow->consumeCaptureEvent(false);
11232 mWindow->consumeFocusEvent(false);
11233 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +090011234 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011235
11236 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011237 notifyPointerCaptureChanged({});
11238 notifyPointerCaptureChanged(request);
11239 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -080011240 mWindow->assertNoEvents();
11241 mSecondWindow->assertNoEvents();
11242 mFakePolicy->assertSetPointerCaptureNotCalled();
11243}
11244
11245TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011246 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011247
11248 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011249 notifyPointerCaptureChanged({});
11250 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011251
11252 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +090011253 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011254 mWindow->consumeCaptureEvent(false);
11255 mWindow->assertNoEvents();
11256}
11257
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011258TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
11259 requestAndVerifyPointerCapture(mWindow, true);
11260
11261 // The first window loses focus.
11262 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +090011263 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011264 mWindow->consumeCaptureEvent(false);
11265
11266 // Request Pointer Capture from the second window before the notification from InputReader
11267 // arrives.
11268 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011269 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011270
11271 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011272 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011273
11274 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011275 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011276
11277 mSecondWindow->consumeFocusEvent(true);
11278 mSecondWindow->consumeCaptureEvent(true);
11279}
11280
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011281TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
11282 // App repeatedly enables and disables capture.
11283 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011284 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011285 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011286 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011287 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011288 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011289
11290 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
11291 // first request is now stale, this should do nothing.
11292 notifyPointerCaptureChanged(firstRequest);
11293 mWindow->assertNoEvents();
11294
11295 // InputReader notifies that the second request was enabled.
11296 notifyPointerCaptureChanged(secondRequest);
11297 mWindow->consumeCaptureEvent(true);
11298}
11299
Prabir Pradhan7092e262022-05-03 16:51:09 +000011300TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
11301 requestAndVerifyPointerCapture(mWindow, true);
11302
11303 // App toggles pointer capture off and on.
11304 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011305 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011306
11307 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011308 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011309
11310 // InputReader notifies that the latest "enable" request was processed, while skipping over the
11311 // preceding "disable" request.
11312 notifyPointerCaptureChanged(enableRequest);
11313
11314 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
11315 // any notifications.
11316 mWindow->assertNoEvents();
11317}
11318
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011319/**
11320 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
11321 * mouse movements don't affect the previous mouse hovering state.
11322 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
11323 * HOVER_MOVE events).
11324 */
11325TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
11326 // Mouse hover on the window
11327 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11328 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11329 .build());
11330 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11331 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11332 .build());
11333
11334 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
11335 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
11336
11337 // Start pointer capture
11338 requestAndVerifyPointerCapture(mWindow, true);
11339
11340 // Send some relative mouse movements and receive them in the window.
11341 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
11342 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
11343 .build());
11344 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
11345 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
11346
11347 // Stop pointer capture
11348 requestAndVerifyPointerCapture(mWindow, false);
11349
11350 // Continue hovering on the window
11351 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11352 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
11353 .build());
11354 mWindow->consumeMotionEvent(
11355 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
11356
11357 mWindow->assertNoEvents();
11358}
11359
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011360TEST_F(InputDispatcherPointerCaptureTests, MultiDisplayPointerCapture) {
11361 // The default display is the focused display to begin with.
11362 requestAndVerifyPointerCapture(mWindow, true);
11363
11364 // Move the second window to a second display, make it the focused window on that display.
11365 mSecondWindow->editInfo()->displayId = SECOND_DISPLAY_ID;
11366 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11367 setFocusedWindow(mSecondWindow);
11368 mSecondWindow->consumeFocusEvent(true);
11369
11370 mWindow->assertNoEvents();
11371
11372 // The second window cannot gain capture because it is not on the focused display.
11373 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11374 mFakePolicy->assertSetPointerCaptureNotCalled();
11375 mSecondWindow->assertNoEvents();
11376
11377 // Make the second display the focused display.
11378 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +000011379 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011380
11381 // This causes the first window to lose pointer capture, and it's unable to request capture.
11382 mWindow->consumeCaptureEvent(false);
11383 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11384
11385 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11386 mFakePolicy->assertSetPointerCaptureNotCalled();
11387
11388 // The second window is now able to gain pointer capture successfully.
11389 requestAndVerifyPointerCapture(mSecondWindow, true);
11390}
11391
Hiroki Sato25040232024-02-22 17:21:22 +090011392using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
11393
11394TEST_F(InputDispatcherPointerCaptureDeathTest,
11395 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
11396 testing::GTEST_FLAG(death_test_style) = "threadsafe";
11397 ScopedSilentDeath _silentDeath;
11398
11399 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11400 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11401
11402 // Dispatch a pointer changed event with a wrong token.
11403 request.window = mSecondWindow->getToken();
11404 ASSERT_DEATH(
11405 {
11406 notifyPointerCaptureChanged(request);
11407 mSecondWindow->consumeCaptureEvent(true);
11408 },
11409 "Unexpected requested window for Pointer Capture.");
11410}
11411
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011412class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
11413protected:
11414 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000011415
11416 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
11417 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
11418
11419 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
11420 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11421
11422 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
11423 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
11424 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11425 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
11426 MAXIMUM_OBSCURING_OPACITY);
11427
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011428 static constexpr gui::Uid TOUCHED_APP_UID{10001};
11429 static constexpr gui::Uid APP_B_UID{10002};
11430 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011431
11432 sp<FakeWindowHandle> mTouchWindow;
11433
11434 virtual void SetUp() override {
11435 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011436 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011437 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
11438 }
11439
11440 virtual void TearDown() override {
11441 InputDispatcherTest::TearDown();
11442 mTouchWindow.clear();
11443 }
11444
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011445 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050011446 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011447 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011448 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011449 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011450 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011451 return window;
11452 }
11453
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011454 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011455 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
11456 sp<FakeWindowHandle> window =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011457 sp<FakeWindowHandle>::make(app, mDispatcher, name, ui::LogicalDisplayId::DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011458 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011459 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011460 return window;
11461 }
11462
11463 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011464 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011465 AINPUT_SOURCE_TOUCHSCREEN,
11466 ui::LogicalDisplayId::DEFAULT, points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011467 }
11468};
11469
11470TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011471 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011472 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011473 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011474
11475 touch();
11476
11477 mTouchWindow->assertNoEvents();
11478}
11479
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011480TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000011481 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
11482 const sp<FakeWindowHandle>& w =
11483 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011484 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011485
11486 touch();
11487
11488 mTouchWindow->assertNoEvents();
11489}
11490
11491TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011492 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
11493 const sp<FakeWindowHandle>& w =
11494 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011495 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011496
11497 touch();
11498
11499 w->assertNoEvents();
11500}
11501
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011502TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011503 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011504 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011505
11506 touch();
11507
11508 mTouchWindow->consumeAnyMotionDown();
11509}
11510
11511TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011512 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011513 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011514 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011515 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011516
11517 touch({PointF{100, 100}});
11518
11519 mTouchWindow->consumeAnyMotionDown();
11520}
11521
11522TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011523 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011524 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011525 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011526
11527 touch();
11528
11529 mTouchWindow->consumeAnyMotionDown();
11530}
11531
11532TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
11533 const sp<FakeWindowHandle>& w =
11534 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011535 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011536
11537 touch();
11538
11539 mTouchWindow->consumeAnyMotionDown();
11540}
11541
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011542TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
11543 const sp<FakeWindowHandle>& w =
11544 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011545 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011546
11547 touch();
11548
11549 w->assertNoEvents();
11550}
11551
11552/**
11553 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
11554 * inside) while letting them pass-through. Note that even though touch passes through the occluding
11555 * window, the occluding window will still receive ACTION_OUTSIDE event.
11556 */
11557TEST_F(InputDispatcherUntrustedTouchesTest,
11558 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
11559 const sp<FakeWindowHandle>& w =
11560 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011561 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011562 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011563
11564 touch();
11565
11566 w->consumeMotionOutside();
11567}
11568
11569TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
11570 const sp<FakeWindowHandle>& w =
11571 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011572 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011573 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011574
11575 touch();
11576
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011577 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011578}
11579
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011580TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011581 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011582 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11583 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011584 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011585
11586 touch();
11587
11588 mTouchWindow->consumeAnyMotionDown();
11589}
11590
11591TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
11592 const sp<FakeWindowHandle>& w =
11593 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11594 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011595 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011596
11597 touch();
11598
11599 mTouchWindow->consumeAnyMotionDown();
11600}
11601
11602TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011603 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011604 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11605 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011606 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011607
11608 touch();
11609
11610 mTouchWindow->assertNoEvents();
11611}
11612
11613TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
11614 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
11615 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011616 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11617 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011618 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011619 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11620 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011621 mDispatcher->onWindowInfosChanged(
11622 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011623
11624 touch();
11625
11626 mTouchWindow->assertNoEvents();
11627}
11628
11629TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
11630 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
11631 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011632 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11633 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011634 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011635 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11636 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011637 mDispatcher->onWindowInfosChanged(
11638 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011639
11640 touch();
11641
11642 mTouchWindow->consumeAnyMotionDown();
11643}
11644
11645TEST_F(InputDispatcherUntrustedTouchesTest,
11646 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
11647 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011648 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11649 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011650 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011651 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11652 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011653 mDispatcher->onWindowInfosChanged(
11654 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011655
11656 touch();
11657
11658 mTouchWindow->consumeAnyMotionDown();
11659}
11660
11661TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
11662 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011663 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11664 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011665 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011666 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11667 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011668 mDispatcher->onWindowInfosChanged(
11669 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011670
11671 touch();
11672
11673 mTouchWindow->assertNoEvents();
11674}
11675
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011676TEST_F(InputDispatcherUntrustedTouchesTest,
11677 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
11678 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011679 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11680 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011681 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011682 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11683 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011684 mDispatcher->onWindowInfosChanged(
11685 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011686
11687 touch();
11688
11689 mTouchWindow->assertNoEvents();
11690}
11691
11692TEST_F(InputDispatcherUntrustedTouchesTest,
11693 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
11694 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011695 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11696 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011697 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011698 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11699 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011700 mDispatcher->onWindowInfosChanged(
11701 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011702
11703 touch();
11704
11705 mTouchWindow->consumeAnyMotionDown();
11706}
11707
11708TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
11709 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011710 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11711 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011712 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011713
11714 touch();
11715
11716 mTouchWindow->consumeAnyMotionDown();
11717}
11718
11719TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
11720 const sp<FakeWindowHandle>& w =
11721 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011722 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011723
11724 touch();
11725
11726 mTouchWindow->consumeAnyMotionDown();
11727}
11728
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011729TEST_F(InputDispatcherUntrustedTouchesTest,
11730 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
11731 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11732 const sp<FakeWindowHandle>& w =
11733 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011734 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011735
11736 touch();
11737
11738 mTouchWindow->assertNoEvents();
11739}
11740
11741TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
11742 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11743 const sp<FakeWindowHandle>& w =
11744 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011745 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011746
11747 touch();
11748
11749 mTouchWindow->consumeAnyMotionDown();
11750}
11751
11752TEST_F(InputDispatcherUntrustedTouchesTest,
11753 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
11754 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
11755 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011756 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11757 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011758 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011759
11760 touch();
11761
11762 mTouchWindow->consumeAnyMotionDown();
11763}
11764
11765TEST_F(InputDispatcherUntrustedTouchesTest,
11766 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
11767 const sp<FakeWindowHandle>& w1 =
11768 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11769 OPACITY_BELOW_THRESHOLD);
11770 const sp<FakeWindowHandle>& w2 =
11771 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11772 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011773 mDispatcher->onWindowInfosChanged(
11774 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011775
11776 touch();
11777
11778 mTouchWindow->assertNoEvents();
11779}
11780
11781/**
11782 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
11783 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
11784 * (which alone would result in allowing touches) does not affect the blocking behavior.
11785 */
11786TEST_F(InputDispatcherUntrustedTouchesTest,
11787 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
11788 const sp<FakeWindowHandle>& wB =
11789 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11790 OPACITY_BELOW_THRESHOLD);
11791 const sp<FakeWindowHandle>& wC =
11792 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11793 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011794 mDispatcher->onWindowInfosChanged(
11795 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011796
11797 touch();
11798
11799 mTouchWindow->assertNoEvents();
11800}
11801
11802/**
11803 * This test is testing that a window from a different UID but with same application token doesn't
11804 * block the touch. Apps can share the application token for close UI collaboration for example.
11805 */
11806TEST_F(InputDispatcherUntrustedTouchesTest,
11807 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
11808 const sp<FakeWindowHandle>& w =
11809 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
11810 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011811 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011812
11813 touch();
11814
11815 mTouchWindow->consumeAnyMotionDown();
11816}
11817
arthurhungb89ccb02020-12-30 16:19:01 +080011818class InputDispatcherDragTests : public InputDispatcherTest {
11819protected:
11820 std::shared_ptr<FakeApplicationHandle> mApp;
11821 sp<FakeWindowHandle> mWindow;
11822 sp<FakeWindowHandle> mSecondWindow;
11823 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011824 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011825 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
11826 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080011827
11828 void SetUp() override {
11829 InputDispatcherTest::SetUp();
11830 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011831 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11832 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011833 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011834
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011835 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11836 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011837 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011838
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011839 mSpyWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow",
11840 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011841 mSpyWindow->setSpy(true);
11842 mSpyWindow->setTrustedOverlay(true);
11843 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
11844
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011845 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011846 mDispatcher->onWindowInfosChanged(
11847 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
11848 {},
11849 0,
11850 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011851 }
11852
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011853 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
11854 switch (fromSource) {
11855 case AINPUT_SOURCE_TOUCHSCREEN:
11856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011857 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011858 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11860 break;
11861 case AINPUT_SOURCE_STYLUS:
11862 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011863 injectMotionEvent(*mDispatcher,
11864 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11865 AINPUT_SOURCE_STYLUS)
11866 .buttonState(
11867 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
11868 .pointer(PointerBuilder(0, ToolType::STYLUS)
11869 .x(50)
11870 .y(50))
11871 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011872 break;
11873 case AINPUT_SOURCE_MOUSE:
11874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011875 injectMotionEvent(*mDispatcher,
11876 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11877 AINPUT_SOURCE_MOUSE)
11878 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
11879 .pointer(PointerBuilder(MOUSE_POINTER_ID,
11880 ToolType::MOUSE)
11881 .x(50)
11882 .y(50))
11883 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011884 break;
11885 default:
11886 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
11887 }
arthurhungb89ccb02020-12-30 16:19:01 +080011888
11889 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011890 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011891 // Spy window should also receive motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011892 mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011893 }
11894
11895 // Start performing drag, we will create a drag window and transfer touch to it.
11896 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
11897 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011898 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000011899 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011900 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000011901 }
arthurhungb89ccb02020-12-30 16:19:01 +080011902
11903 // The drag window covers the entire display
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011904 mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow",
11905 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011906 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011907 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
11908 *mWindow->getInfo(), *mSecondWindow->getInfo()},
11909 {},
11910 0,
11911 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011912
11913 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000011914 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000011915 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
11916 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000011917 if (transferred) {
11918 mWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011919 mDragWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
11920 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000011921 }
11922 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080011923 }
11924};
11925
11926TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011927 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080011928
11929 // Move on window.
11930 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011931 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011932 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011933 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011934 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11935 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011936 mWindow->consumeDragEvent(false, 50, 50);
11937 mSecondWindow->assertNoEvents();
11938
11939 // Move to another window.
11940 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011941 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011942 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011943 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011944 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11945 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011946 mWindow->consumeDragEvent(true, 150, 50);
11947 mSecondWindow->consumeDragEvent(false, 50, 50);
11948
11949 // Move back to original window.
11950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011951 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011952 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011953 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011954 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11955 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011956 mWindow->consumeDragEvent(false, 50, 50);
11957 mSecondWindow->consumeDragEvent(true, -50, 50);
11958
11959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011960 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011961 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011962 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011963 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011964 mWindow->assertNoEvents();
11965 mSecondWindow->assertNoEvents();
11966}
11967
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011968TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011969 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011970
11971 // No cancel event after drag start
11972 mSpyWindow->assertNoEvents();
11973
11974 const MotionEvent secondFingerDownEvent =
11975 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11976 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011977 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11978 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011979 .build();
11980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011981 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011982 InputEventInjectionSync::WAIT_FOR_RESULT))
11983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11984
11985 // Receives cancel for first pointer after next pointer down
11986 mSpyWindow->consumeMotionCancel();
11987 mSpyWindow->consumeMotionDown();
11988
11989 mSpyWindow->assertNoEvents();
11990}
11991
arthurhungf452d0b2021-01-06 00:19:52 +080011992TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011993 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080011994
11995 // Move on window.
11996 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011997 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011998 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080011999 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012000 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12001 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080012002 mWindow->consumeDragEvent(false, 50, 50);
12003 mSecondWindow->assertNoEvents();
12004
12005 // Move to another window.
12006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012007 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012008 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080012009 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012010 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12011 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080012012 mWindow->consumeDragEvent(true, 150, 50);
12013 mSecondWindow->consumeDragEvent(false, 50, 50);
12014
12015 // drop to another window.
12016 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012017 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080012018 {150, 50}))
12019 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012020 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012021 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080012022 mWindow->assertNoEvents();
12023 mSecondWindow->assertNoEvents();
12024}
12025
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012026TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
12027 startDrag();
12028
12029 // No cancel event after drag start
12030 mSpyWindow->assertNoEvents();
12031
12032 const MotionEvent secondFingerDownEvent =
12033 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12034 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12035 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12036 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
12037 .build();
12038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12039 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12040 InputEventInjectionSync::WAIT_FOR_RESULT))
12041 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12042
12043 // Receives cancel for first pointer after next pointer down
12044 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080012045 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012046 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
12047
12048 mSpyWindow->assertNoEvents();
12049
12050 // Spy window calls pilfer pointers
12051 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
12052 mDragWindow->assertNoEvents();
12053
12054 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080012055 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012056 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12057 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
12058 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
12059 .build();
12060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080012061 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012062 InputEventInjectionSync::WAIT_FOR_RESULT))
12063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12064
12065 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000012066 mDragWindow->consumeMotionEvent(
12067 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012068 mDragWindow->assertNoEvents();
12069}
12070
arthurhung6d4bed92021-03-17 11:59:33 +080012071TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012072 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080012073
12074 // Move on window and keep button pressed.
12075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012076 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012077 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
12078 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012079 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012080 .build()))
12081 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012082 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12083 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012084 mWindow->consumeDragEvent(false, 50, 50);
12085 mSecondWindow->assertNoEvents();
12086
12087 // Move to another window and release button, expect to drop item.
12088 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012089 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012090 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
12091 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012092 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012093 .build()))
12094 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012095 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12096 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012097 mWindow->assertNoEvents();
12098 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012099 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080012100
12101 // nothing to the window.
12102 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012103 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012104 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
12105 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012106 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012107 .build()))
12108 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012109 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012110 mWindow->assertNoEvents();
12111 mSecondWindow->assertNoEvents();
12112}
12113
Arthur Hung54745652022-04-20 07:17:41 +000012114TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012115 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080012116
12117 // Set second window invisible.
12118 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012119 mDispatcher->onWindowInfosChanged(
12120 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080012121
12122 // Move on window.
12123 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012124 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012125 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080012126 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012127 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12128 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012129 mWindow->consumeDragEvent(false, 50, 50);
12130 mSecondWindow->assertNoEvents();
12131
12132 // Move to another window.
12133 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012134 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012135 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080012136 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012137 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12138 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012139 mWindow->consumeDragEvent(true, 150, 50);
12140 mSecondWindow->assertNoEvents();
12141
12142 // drop to another window.
12143 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012144 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080012145 {150, 50}))
12146 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012147 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012148 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012149 mWindow->assertNoEvents();
12150 mSecondWindow->assertNoEvents();
12151}
12152
Arthur Hung54745652022-04-20 07:17:41 +000012153TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012154 // Ensure window could track pointerIds if it didn't support split touch.
12155 mWindow->setPreventSplitting(true);
12156
Arthur Hung54745652022-04-20 07:17:41 +000012157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012158 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12159 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000012160 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012161 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012162
12163 const MotionEvent secondFingerDownEvent =
12164 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012165 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000012166 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012167 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12168 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012169 .build();
12170 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012171 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012172 InputEventInjectionSync::WAIT_FOR_RESULT))
12173 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000012174 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000012175
12176 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012177 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000012178}
12179
12180TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
12181 // First down on second window.
12182 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012183 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12184 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000012185 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12186
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012187 mSecondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012188
12189 // Second down on first window.
12190 const MotionEvent secondFingerDownEvent =
12191 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012192 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000012193 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012194 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12195 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012196 .build();
12197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012198 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012199 InputEventInjectionSync::WAIT_FOR_RESULT))
12200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012201 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12202 mSecondWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012203
12204 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012205 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000012206
12207 // Move on window.
12208 const MotionEvent secondFingerMoveEvent =
12209 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12210 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012211 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12212 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012213 .build();
12214 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012215 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012216 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012217 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12218 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000012219 mWindow->consumeDragEvent(false, 50, 50);
12220 mSecondWindow->consumeMotionMove();
12221
12222 // Release the drag pointer should perform drop.
12223 const MotionEvent secondFingerUpEvent =
12224 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12225 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012226 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12227 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012228 .build();
12229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012230 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012231 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012232 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012233 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000012234 mWindow->assertNoEvents();
12235 mSecondWindow->consumeMotionMove();
12236}
12237
Arthur Hung3915c1f2022-05-31 07:17:17 +000012238TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012239 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000012240
12241 // Update window of second display.
12242 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012243 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012244 mDispatcher->onWindowInfosChanged(
12245 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12246 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12247 {},
12248 0,
12249 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012250
12251 // Let second display has a touch state.
12252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012253 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012254 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12255 AINPUT_SOURCE_TOUCHSCREEN)
12256 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012257 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012258 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000012259 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012260 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012261 mDispatcher->onWindowInfosChanged(
12262 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12263 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12264 {},
12265 0,
12266 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012267
12268 // Move on window.
12269 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012270 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012271 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012272 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012273 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12274 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012275 mWindow->consumeDragEvent(false, 50, 50);
12276 mSecondWindow->assertNoEvents();
12277
12278 // Move to another window.
12279 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012280 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012281 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012282 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012283 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12284 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012285 mWindow->consumeDragEvent(true, 150, 50);
12286 mSecondWindow->consumeDragEvent(false, 50, 50);
12287
12288 // drop to another window.
12289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012290 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012291 {150, 50}))
12292 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012293 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012294 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000012295 mWindow->assertNoEvents();
12296 mSecondWindow->assertNoEvents();
12297}
12298
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012299TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
12300 startDrag(true, AINPUT_SOURCE_MOUSE);
12301 // Move on window.
12302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012303 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012304 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12305 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012306 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012307 .x(50)
12308 .y(50))
12309 .build()))
12310 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012311 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12312 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012313 mWindow->consumeDragEvent(false, 50, 50);
12314 mSecondWindow->assertNoEvents();
12315
12316 // Move to another window.
12317 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012318 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012319 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12320 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012321 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012322 .x(150)
12323 .y(50))
12324 .build()))
12325 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012326 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12327 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012328 mWindow->consumeDragEvent(true, 150, 50);
12329 mSecondWindow->consumeDragEvent(false, 50, 50);
12330
12331 // drop to another window.
12332 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012333 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012334 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
12335 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012336 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012337 .x(150)
12338 .y(50))
12339 .build()))
12340 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012341 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012342 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012343 mWindow->assertNoEvents();
12344 mSecondWindow->assertNoEvents();
12345}
12346
Linnan Li5af92f92023-07-14 14:36:22 +080012347/**
12348 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
12349 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
12350 */
12351TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
12352 // Down on second window
12353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012354 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12355 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012356 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12357
12358 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
12359 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
12360
12361 // Down on first window
12362 const MotionEvent secondFingerDownEvent =
12363 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012364 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012365 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12366 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12367 .build();
12368 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12369 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12370 InputEventInjectionSync::WAIT_FOR_RESULT))
12371 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12372 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12373 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
12374 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
12375
12376 // Start drag on first window
12377 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
12378
12379 // Trigger cancel
12380 mDispatcher->cancelCurrentTouch();
12381 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012382 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +000012383 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080012384 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
12385
12386 ASSERT_TRUE(mDispatcher->waitForIdle());
12387 // The D&D finished with nullptr
12388 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
12389
12390 // Remove drag window
12391 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
12392
12393 // Inject a simple gesture, ensure dispatcher not crashed
12394 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012395 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12396 ui::LogicalDisplayId::DEFAULT, PointF{50, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012397 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12398 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12399
12400 const MotionEvent moveEvent =
12401 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012402 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012403 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12404 .build();
12405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12406 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
12407 InputEventInjectionSync::WAIT_FOR_RESULT))
12408 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12409 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
12410
12411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012412 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Li5af92f92023-07-14 14:36:22 +080012413 {50, 50}))
12414 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12415 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
12416}
12417
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012418TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
12419 // Start hovering over the window.
12420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12421 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012422 ui::LogicalDisplayId::DEFAULT, {50, 50}));
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012423
12424 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12425 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12426
12427 ASSERT_FALSE(startDrag(/*sendDown=*/false))
12428 << "Drag and drop should not work with a hovering pointer";
12429}
12430
Vishnu Nair062a8672021-09-03 16:07:44 -070012431class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
12432
12433TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
12434 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012435 sp<FakeWindowHandle> window =
12436 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12437 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012438 window->setDropInput(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012439 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012440 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012441 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012442 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012443 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012444
12445 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012446 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012447 window->assertNoEvents();
12448
Prabir Pradhan678438e2023-04-13 19:32:51 +000012449 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012450 AINPUT_SOURCE_TOUCHSCREEN,
12451 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012452 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012453 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080012454 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070012455 window->assertNoEvents();
12456
12457 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012458 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012459 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012460
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012461 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12462 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012463
Prabir Pradhan678438e2023-04-13 19:32:51 +000012464 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012465 AINPUT_SOURCE_TOUCHSCREEN,
12466 ui::LogicalDisplayId::DEFAULT));
12467 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012468 window->assertNoEvents();
12469}
12470
12471TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
12472 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12473 std::make_shared<FakeApplicationHandle>();
12474 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012475 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012476 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012477 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012478 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012479 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012480 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012481 sp<FakeWindowHandle> window =
12482 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12483 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012484 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012485 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012486 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012487 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012488 mDispatcher->onWindowInfosChanged(
12489 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012490 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012491 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012492
12493 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012494 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012495 window->assertNoEvents();
12496
Prabir Pradhan678438e2023-04-13 19:32:51 +000012497 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012498 AINPUT_SOURCE_TOUCHSCREEN,
12499 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012500 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012501 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012502 window->assertNoEvents();
12503
12504 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012505 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012506 mDispatcher->onWindowInfosChanged(
12507 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012508
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012509 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12510 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012511
Prabir Pradhan678438e2023-04-13 19:32:51 +000012512 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012513 AINPUT_SOURCE_TOUCHSCREEN,
12514 ui::LogicalDisplayId::DEFAULT));
12515 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
12516 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Vishnu Nair062a8672021-09-03 16:07:44 -070012517 window->assertNoEvents();
12518}
12519
12520TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
12521 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12522 std::make_shared<FakeApplicationHandle>();
12523 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012524 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012525 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012526 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012527 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012528 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012529 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012530 sp<FakeWindowHandle> window =
12531 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12532 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012533 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012534 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012535 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012536 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012537 mDispatcher->onWindowInfosChanged(
12538 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012539 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012540 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012541
12542 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012543 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012544 window->assertNoEvents();
12545
Prabir Pradhan678438e2023-04-13 19:32:51 +000012546 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012547 AINPUT_SOURCE_TOUCHSCREEN,
12548 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012549 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012550 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012551 window->assertNoEvents();
12552
12553 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012554 mDispatcher->onWindowInfosChanged(
12555 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012556
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012557 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12558 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012559
Prabir Pradhan678438e2023-04-13 19:32:51 +000012560 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012561 AINPUT_SOURCE_TOUCHSCREEN,
12562 ui::LogicalDisplayId::DEFAULT));
12563 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012564 window->assertNoEvents();
12565}
12566
Antonio Kantekf16f2832021-09-28 04:39:20 +000012567class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
12568protected:
12569 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000012570 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012571 sp<FakeWindowHandle> mWindow;
12572 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000012573 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012574
12575 void SetUp() override {
12576 InputDispatcherTest::SetUp();
12577
12578 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000012579 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012580 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
12581 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012582 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012583 setFocusedWindow(mWindow);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012584 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
12585 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012586 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000012587 mThirdWindow =
12588 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
12589 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
12590 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012591
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012592 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012593 mDispatcher->onWindowInfosChanged(
12594 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
12595 {},
12596 0,
12597 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000012598 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012599 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012600
Antonio Kantek15beb512022-06-13 22:35:41 +000012601 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012602 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012603 WINDOW_UID, /*hasPermission=*/true,
12604 ui::LogicalDisplayId::DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070012605 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
12606 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012607 mThirdWindow->assertNoEvents();
12608 }
12609
12610 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
12611 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000012612 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000012613 SECOND_DISPLAY_ID)) {
12614 mWindow->assertNoEvents();
12615 mSecondWindow->assertNoEvents();
12616 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070012617 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000012618 }
12619
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012620 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000012621 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070012622 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012623 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012624 mWindow->consumeTouchModeEvent(inTouchMode);
12625 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012626 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000012627 }
12628};
12629
Antonio Kantek26defcf2022-02-08 01:12:27 +000012630TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012631 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000012632 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
12633 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012634 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012635}
12636
Antonio Kantek26defcf2022-02-08 01:12:27 +000012637TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
12638 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012639 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012640 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012641 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012642 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012643 ownerUid, /*hasPermission=*/false,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012644 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000012645 mWindow->assertNoEvents();
12646 mSecondWindow->assertNoEvents();
12647}
12648
12649TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
12650 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012651 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012652 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012653 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000012654 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012655 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012656}
12657
Antonio Kantekf16f2832021-09-28 04:39:20 +000012658TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012659 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000012660 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
12661 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012662 /*hasPermission=*/true,
12663 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012664 mWindow->assertNoEvents();
12665 mSecondWindow->assertNoEvents();
12666}
12667
Antonio Kantek15beb512022-06-13 22:35:41 +000012668TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
12669 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
12670 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12671 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012672 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000012673 mWindow->assertNoEvents();
12674 mSecondWindow->assertNoEvents();
12675 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
12676}
12677
Antonio Kantek48710e42022-03-24 14:19:30 -070012678TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
12679 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012680 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012681 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070012682 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012683 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Antonio Kantek48710e42022-03-24 14:19:30 -070012684
12685 // Then remove focus.
12686 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012687 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070012688
12689 // Assert that caller can switch touch mode by owning one of the last interacted window.
12690 const WindowInfo& windowInfo = *mWindow->getInfo();
12691 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12692 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012693 /*hasPermission=*/false,
12694 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070012695}
12696
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012697class InputDispatcherSpyWindowTest : public InputDispatcherTest {
12698public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012699 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012700 std::shared_ptr<FakeApplicationHandle> application =
12701 std::make_shared<FakeApplicationHandle>();
12702 std::string name = "Fake Spy ";
12703 name += std::to_string(mSpyCount++);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012704 sp<FakeWindowHandle> spy =
12705 sp<FakeWindowHandle>::make(application, mDispatcher, name.c_str(),
12706 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012707 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012708 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012709 return spy;
12710 }
12711
12712 sp<FakeWindowHandle> createForeground() {
12713 std::shared_ptr<FakeApplicationHandle> application =
12714 std::make_shared<FakeApplicationHandle>();
12715 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012716 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012717 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012718 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012719 return window;
12720 }
12721
12722private:
12723 int mSpyCount{0};
12724};
12725
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012726using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012727/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012728 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
12729 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012730TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070012731 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012732 ScopedSilentDeath _silentDeath;
12733
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012734 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012735 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012736 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012737 ".* not a trusted overlay");
12738}
12739
12740/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012741 * Input injection into a display with a spy window but no foreground windows should succeed.
12742 */
12743TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012744 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012745 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012746
12747 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012748 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12749 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012750 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012751 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012752}
12753
12754/**
12755 * Verify the order in which different input windows receive events. The touched foreground window
12756 * (if there is one) should always receive the event first. When there are multiple spy windows, the
12757 * spy windows will receive the event according to their Z-order, where the top-most spy window will
12758 * receive events before ones belows it.
12759 *
12760 * Here, we set up a scenario with four windows in the following Z order from the top:
12761 * spy1, spy2, window, spy3.
12762 * We then inject an event and verify that the foreground "window" receives it first, followed by
12763 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
12764 * window.
12765 */
12766TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
12767 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012768 auto spy1 = createSpy();
12769 auto spy2 = createSpy();
12770 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012771 mDispatcher->onWindowInfosChanged(
12772 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012773 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
12774 const size_t numChannels = channels.size();
12775
Michael Wright8e9a8562022-02-09 13:44:29 +000012776 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012777 if (!epollFd.ok()) {
12778 FAIL() << "Failed to create epoll fd";
12779 }
12780
12781 for (size_t i = 0; i < numChannels; i++) {
12782 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
12783 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
12784 FAIL() << "Failed to add fd to epoll";
12785 }
12786 }
12787
12788 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012789 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12790 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012791 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12792
12793 std::vector<size_t> eventOrder;
12794 std::vector<struct epoll_event> events(numChannels);
12795 for (;;) {
12796 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
12797 (100ms).count());
12798 if (nFds < 0) {
12799 FAIL() << "Failed to call epoll_wait";
12800 }
12801 if (nFds == 0) {
12802 break; // epoll_wait timed out
12803 }
12804 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070012805 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070012806 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012807 channels[i]->consumeMotionDown();
12808 }
12809 }
12810
12811 // Verify the order in which the events were received.
12812 EXPECT_EQ(3u, eventOrder.size());
12813 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
12814 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
12815 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
12816}
12817
12818/**
12819 * A spy window using the NOT_TOUCHABLE flag does not receive events.
12820 */
12821TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
12822 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012823 auto spy = createSpy();
12824 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012825 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012826
12827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012828 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12829 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012830 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012831 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012832 spy->assertNoEvents();
12833}
12834
12835/**
12836 * A spy window will only receive gestures that originate within its touchable region. Gestures that
12837 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
12838 * to the window.
12839 */
12840TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
12841 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012842 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012843 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012844 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012845
12846 // Inject an event outside the spy window's touchable region.
12847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012848 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12849 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012850 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12851 window->consumeMotionDown();
12852 spy->assertNoEvents();
12853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012854 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12855 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012856 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12857 window->consumeMotionUp();
12858 spy->assertNoEvents();
12859
12860 // Inject an event inside the spy window's touchable region.
12861 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012862 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12863 ui::LogicalDisplayId::DEFAULT, {5, 10}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012864 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12865 window->consumeMotionDown();
12866 spy->consumeMotionDown();
12867}
12868
12869/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012870 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012871 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012872 */
12873TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
12874 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012875 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012876 auto spy = createSpy();
12877 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012878 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012879 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012880 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012881
12882 // Inject an event outside the spy window's frame and touchable region.
12883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012884 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12885 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012886 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12887 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012888 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012889}
12890
12891/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012892 * Even when a spy window spans over multiple foreground windows, the spy should receive all
12893 * pointers that are down within its bounds.
12894 */
12895TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
12896 auto windowLeft = createForeground();
12897 windowLeft->setFrame({0, 0, 100, 200});
12898 auto windowRight = createForeground();
12899 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012900 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012901 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012902 mDispatcher->onWindowInfosChanged(
12903 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012904
12905 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012906 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12907 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012908 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12909 windowLeft->consumeMotionDown();
12910 spy->consumeMotionDown();
12911
12912 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012913 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012914 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012915 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12916 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012917 .build();
12918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012919 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012920 InputEventInjectionSync::WAIT_FOR_RESULT))
12921 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12922 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000012923 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012924}
12925
12926/**
12927 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
12928 * the spy should receive the second pointer with ACTION_DOWN.
12929 */
12930TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
12931 auto window = createForeground();
12932 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012933 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012934 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012935 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012936
12937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012938 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12939 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012940 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12941 window->consumeMotionDown();
12942 spyRight->assertNoEvents();
12943
12944 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012945 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012946 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012947 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12948 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012949 .build();
12950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012951 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012952 InputEventInjectionSync::WAIT_FOR_RESULT))
12953 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000012954 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012955 spyRight->consumeMotionDown();
12956}
12957
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012958/**
12959 * The spy window should not be able to affect whether or not touches are split. Only the foreground
12960 * windows should be allowed to control split touch.
12961 */
12962TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080012963 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012964 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012965 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080012966 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012967
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012968 auto window = createForeground();
12969 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012970
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012971 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012972
12973 // First finger down, no window touched.
12974 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012975 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12976 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012977 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012978 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012979 window->assertNoEvents();
12980
12981 // Second finger down on window, the window should receive touch down.
12982 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012983 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012984 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012985 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012986 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12987 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012988 .build();
12989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012990 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012991 InputEventInjectionSync::WAIT_FOR_RESULT))
12992 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12993
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012994 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000012995 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012996}
12997
12998/**
12999 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
13000 * do not receive key events.
13001 */
13002TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013003 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013004 spy->setFocusable(false);
13005
13006 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013007 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013008 setFocusedWindow(window);
13009 window->consumeFocusEvent(true);
13010
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013011 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013012 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013013 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013014
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013015 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013016 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013017 window->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013018
13019 spy->assertNoEvents();
13020}
13021
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013022using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
13023
13024/**
13025 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
13026 * are currently sent to any other windows - including other spy windows - will also be cancelled.
13027 */
13028TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
13029 auto window = createForeground();
13030 auto spy1 = createSpy();
13031 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013032 mDispatcher->onWindowInfosChanged(
13033 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013034
13035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013036 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13037 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013038 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13039 window->consumeMotionDown();
13040 spy1->consumeMotionDown();
13041 spy2->consumeMotionDown();
13042
13043 // Pilfer pointers from the second spy window.
13044 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
13045 spy2->assertNoEvents();
13046 spy1->consumeMotionCancel();
13047 window->consumeMotionCancel();
13048
13049 // The rest of the gesture should only be sent to the second spy window.
13050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013051 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013052 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013053 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13054 spy2->consumeMotionMove();
13055 spy1->assertNoEvents();
13056 window->assertNoEvents();
13057}
13058
13059/**
13060 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
13061 * in the middle of the gesture.
13062 */
13063TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
13064 auto window = createForeground();
13065 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013066 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013067
13068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013069 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13070 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013071 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013072 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13073 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013074
13075 window->releaseChannel();
13076
13077 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13078
13079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013080 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13081 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013082 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013083 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013084}
13085
13086/**
13087 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
13088 * the spy, but not to any other windows.
13089 */
13090TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
13091 auto spy = createSpy();
13092 auto window = createForeground();
13093
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013094 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013095
13096 // First finger down on the window and the spy.
13097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013098 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13099 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013100 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13101 spy->consumeMotionDown();
13102 window->consumeMotionDown();
13103
13104 // Spy window pilfers the pointers.
13105 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13106 window->consumeMotionCancel();
13107
13108 // Second finger down on the window and spy, but the window should not receive the pointer down.
13109 const MotionEvent secondFingerDownEvent =
13110 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013111 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013112 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013113 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13114 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013115 .build();
13116 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013117 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013118 InputEventInjectionSync::WAIT_FOR_RESULT))
13119 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13120
Harry Cutts33476232023-01-30 19:57:29 +000013121 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013122
13123 // Third finger goes down outside all windows, so injection should fail.
13124 const MotionEvent thirdFingerDownEvent =
13125 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013126 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013127 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013128 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13129 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
13130 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013131 .build();
13132 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013133 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013134 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080013135 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013136
13137 spy->assertNoEvents();
13138 window->assertNoEvents();
13139}
13140
13141/**
13142 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
13143 */
13144TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
13145 auto spy = createSpy();
13146 spy->setFrame(Rect(0, 0, 100, 100));
13147 auto window = createForeground();
13148 window->setFrame(Rect(0, 0, 200, 200));
13149
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013150 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013151
13152 // First finger down on the window only
13153 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013154 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13155 ui::LogicalDisplayId::DEFAULT, {150, 150}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013156 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13157 window->consumeMotionDown();
13158
13159 // Second finger down on the spy and window
13160 const MotionEvent secondFingerDownEvent =
13161 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013162 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013163 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013164 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13165 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013166 .build();
13167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013168 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013169 InputEventInjectionSync::WAIT_FOR_RESULT))
13170 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13171 spy->consumeMotionDown();
13172 window->consumeMotionPointerDown(1);
13173
13174 // Third finger down on the spy and window
13175 const MotionEvent thirdFingerDownEvent =
13176 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013177 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013178 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013179 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13180 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
13181 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013182 .build();
13183 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013184 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013185 InputEventInjectionSync::WAIT_FOR_RESULT))
13186 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13187 spy->consumeMotionPointerDown(1);
13188 window->consumeMotionPointerDown(2);
13189
13190 // Spy window pilfers the pointers.
13191 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +000013192 window->consumeMotionPointerUp(/*pointerIdx=*/2,
13193 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13194 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13195 WithPointerCount(3)));
13196 window->consumeMotionPointerUp(/*pointerIdx=*/1,
13197 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13198 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13199 WithPointerCount(2)));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013200
13201 spy->assertNoEvents();
13202 window->assertNoEvents();
13203}
13204
13205/**
13206 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
13207 * other windows should be canceled. If this results in the cancellation of all pointers for some
13208 * window, then that window should receive ACTION_CANCEL.
13209 */
13210TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
13211 auto spy = createSpy();
13212 spy->setFrame(Rect(0, 0, 100, 100));
13213 auto window = createForeground();
13214 window->setFrame(Rect(0, 0, 200, 200));
13215
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013216 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013217
13218 // First finger down on both spy and window
13219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013220 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13221 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013222 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13223 window->consumeMotionDown();
13224 spy->consumeMotionDown();
13225
13226 // Second finger down on the spy and window
13227 const MotionEvent secondFingerDownEvent =
13228 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013229 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013230 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013231 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13232 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013233 .build();
13234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013235 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013236 InputEventInjectionSync::WAIT_FOR_RESULT))
13237 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13238 spy->consumeMotionPointerDown(1);
13239 window->consumeMotionPointerDown(1);
13240
13241 // Spy window pilfers the pointers.
13242 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13243 window->consumeMotionCancel();
13244
13245 spy->assertNoEvents();
13246 window->assertNoEvents();
13247}
13248
13249/**
13250 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
13251 * be sent to other windows
13252 */
13253TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
13254 auto spy = createSpy();
13255 spy->setFrame(Rect(0, 0, 100, 100));
13256 auto window = createForeground();
13257 window->setFrame(Rect(0, 0, 200, 200));
13258
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013259 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013260
13261 // First finger down on both window and spy
13262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013263 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13264 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013265 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13266 window->consumeMotionDown();
13267 spy->consumeMotionDown();
13268
13269 // Spy window pilfers the pointers.
13270 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13271 window->consumeMotionCancel();
13272
13273 // Second finger down on the window only
13274 const MotionEvent secondFingerDownEvent =
13275 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013276 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013277 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013278 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13279 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013280 .build();
13281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013282 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013283 InputEventInjectionSync::WAIT_FOR_RESULT))
13284 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13285 window->consumeMotionDown();
13286 window->assertNoEvents();
13287
13288 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
13289 spy->consumeMotionMove();
13290 spy->assertNoEvents();
13291}
13292
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013293/**
13294 * A window on the left and a window on the right. Also, a spy window that's above all of the
13295 * windows, and spanning both left and right windows.
13296 * Send simultaneous motion streams from two different devices, one to the left window, and another
13297 * to the right window.
13298 * Pilfer from spy window.
13299 * Check that the pilfering only affects the pointers that are actually being received by the spy.
13300 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013301TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer_legacy) {
13302 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013303 sp<FakeWindowHandle> spy = createSpy();
13304 spy->setFrame(Rect(0, 0, 200, 200));
13305 sp<FakeWindowHandle> leftWindow = createForeground();
13306 leftWindow->setFrame(Rect(0, 0, 100, 100));
13307
13308 sp<FakeWindowHandle> rightWindow = createForeground();
13309 rightWindow->setFrame(Rect(100, 0, 200, 100));
13310
13311 constexpr int32_t stylusDeviceId = 1;
13312 constexpr int32_t touchDeviceId = 2;
13313
13314 mDispatcher->onWindowInfosChanged(
13315 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13316
13317 // Stylus down on left window and spy
13318 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13319 .deviceId(stylusDeviceId)
13320 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13321 .build());
13322 leftWindow->consumeMotionEvent(
13323 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13324 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13325
13326 // Finger down on right window and spy - but spy already has stylus
13327 mDispatcher->notifyMotion(
13328 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13329 .deviceId(touchDeviceId)
13330 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13331 .build());
13332 rightWindow->consumeMotionEvent(
13333 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013334 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013335
13336 // Act: pilfer from spy. Spy is currently receiving touch events.
13337 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013338 leftWindow->consumeMotionEvent(
13339 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013340 rightWindow->consumeMotionEvent(
13341 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13342
13343 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
13344 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13345 .deviceId(stylusDeviceId)
13346 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13347 .build());
13348 mDispatcher->notifyMotion(
13349 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13350 .deviceId(touchDeviceId)
13351 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13352 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013353 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013354
13355 spy->assertNoEvents();
13356 leftWindow->assertNoEvents();
13357 rightWindow->assertNoEvents();
13358}
13359
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013360/**
13361 * A window on the left and a window on the right. Also, a spy window that's above all of the
13362 * windows, and spanning both left and right windows.
13363 * Send simultaneous motion streams from two different devices, one to the left window, and another
13364 * to the right window.
13365 * Pilfer from spy window.
13366 * Check that the pilfering affects all of the pointers that are actually being received by the spy.
13367 * The spy should receive both the touch and the stylus events after pilfer.
13368 */
13369TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
13370 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13371 sp<FakeWindowHandle> spy = createSpy();
13372 spy->setFrame(Rect(0, 0, 200, 200));
13373 sp<FakeWindowHandle> leftWindow = createForeground();
13374 leftWindow->setFrame(Rect(0, 0, 100, 100));
13375
13376 sp<FakeWindowHandle> rightWindow = createForeground();
13377 rightWindow->setFrame(Rect(100, 0, 200, 100));
13378
13379 constexpr int32_t stylusDeviceId = 1;
13380 constexpr int32_t touchDeviceId = 2;
13381
13382 mDispatcher->onWindowInfosChanged(
13383 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13384
13385 // Stylus down on left window and spy
13386 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13387 .deviceId(stylusDeviceId)
13388 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13389 .build());
13390 leftWindow->consumeMotionEvent(
13391 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13392 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13393
13394 // Finger down on right window and spy
13395 mDispatcher->notifyMotion(
13396 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13397 .deviceId(touchDeviceId)
13398 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13399 .build());
13400 rightWindow->consumeMotionEvent(
13401 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13402 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13403
13404 // Act: pilfer from spy. Spy is currently receiving touch events.
13405 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13406 leftWindow->consumeMotionEvent(
13407 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
13408 rightWindow->consumeMotionEvent(
13409 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13410
13411 // Continue movements from both stylus and touch. Touch and stylus will be delivered to spy
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013412 // Instead of sending the two MOVE events for each input device together, and then receiving
13413 // them both, process them one at at time. InputConsumer is always in the batching mode, which
13414 // means that the two MOVE events will be initially put into a batch. Once the events are
13415 // batched, the 'consume' call may result in any of the MOVE events to be sent first (depending
13416 // on the implementation of InputConsumer), which would mean that the order of the received
13417 // events could be different depending on whether there are 1 or 2 events pending in the
13418 // InputChannel at the time the test calls 'consume'. To make assertions simpler here, and to
13419 // avoid this confusing behaviour, send and receive each MOVE event separately.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013420 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13421 .deviceId(stylusDeviceId)
13422 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13423 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013424 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013425 mDispatcher->notifyMotion(
13426 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13427 .deviceId(touchDeviceId)
13428 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13429 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013430 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013431
13432 spy->assertNoEvents();
13433 leftWindow->assertNoEvents();
13434 rightWindow->assertNoEvents();
13435}
13436
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000013437TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
13438 auto window = createForeground();
13439 auto spy = createSpy();
13440 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13441
13442 mDispatcher->notifyMotion(
13443 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
13444 .deviceId(1)
13445 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
13446 .build());
13447 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13448 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13449
13450 // Pilfer pointers from the spy window should fail.
13451 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
13452 spy->assertNoEvents();
13453 window->assertNoEvents();
13454}
13455
Prabir Pradhand65552b2021-10-07 11:23:50 -070013456class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
13457public:
13458 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
13459 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13460 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013461 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
13462 "Stylus interceptor window",
13463 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013464 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013465 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013466 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013467 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013468 overlay->setTrustedOverlay(true);
13469
13470 std::shared_ptr<FakeApplicationHandle> application =
13471 std::make_shared<FakeApplicationHandle>();
13472 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013473 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013474 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013475 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013476 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013477
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013478 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013479 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013480 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013481 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013482 return {std::move(overlay), std::move(window)};
13483 }
13484
13485 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000013486 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070013487 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013488 ui::LogicalDisplayId::DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070013489 }
13490
13491 void sendStylusEvent(int32_t action) {
13492 NotifyMotionArgs motionArgs =
13493 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013494 ui::LogicalDisplayId::DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013495 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000013496 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013497 }
13498};
13499
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013500using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
13501
13502TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070013503 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013504 ScopedSilentDeath _silentDeath;
13505
Prabir Pradhand65552b2021-10-07 11:23:50 -070013506 auto [overlay, window] = setupStylusOverlayScenario();
13507 overlay->setTrustedOverlay(false);
13508 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013509 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
13510 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070013511 ".* not a trusted overlay");
13512}
13513
13514TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
13515 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013516 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013517
13518 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13519 overlay->consumeMotionDown();
13520 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13521 overlay->consumeMotionUp();
13522
13523 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13524 window->consumeMotionDown();
13525 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13526 window->consumeMotionUp();
13527
13528 overlay->assertNoEvents();
13529 window->assertNoEvents();
13530}
13531
13532TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
13533 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013534 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013535 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013536
13537 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13538 overlay->consumeMotionDown();
13539 window->consumeMotionDown();
13540 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13541 overlay->consumeMotionUp();
13542 window->consumeMotionUp();
13543
13544 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13545 window->consumeMotionDown();
13546 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13547 window->consumeMotionUp();
13548
13549 overlay->assertNoEvents();
13550 window->assertNoEvents();
13551}
13552
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013553/**
13554 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
13555 * The scenario is as follows:
13556 * - The stylus interceptor overlay is configured as a spy window.
13557 * - The stylus interceptor spy receives the start of a new stylus gesture.
13558 * - It pilfers pointers and then configures itself to no longer be a spy.
13559 * - The stylus interceptor continues to receive the rest of the gesture.
13560 */
13561TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
13562 auto [overlay, window] = setupStylusOverlayScenario();
13563 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013564 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013565
13566 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13567 overlay->consumeMotionDown();
13568 window->consumeMotionDown();
13569
13570 // The interceptor pilfers the pointers.
13571 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
13572 window->consumeMotionCancel();
13573
13574 // The interceptor configures itself so that it is no longer a spy.
13575 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013576 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013577
13578 // It continues to receive the rest of the stylus gesture.
13579 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
13580 overlay->consumeMotionMove();
13581 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13582 overlay->consumeMotionUp();
13583
13584 window->assertNoEvents();
13585}
13586
Prabir Pradhan5735a322022-04-11 17:23:34 +000013587struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013588 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013589 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000013590 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
13591 std::unique_ptr<InputDispatcher>& mDispatcher;
13592
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013593 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000013594 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
13595
13596 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013597 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013598 ui::LogicalDisplayId::DEFAULT, {100, 200},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013599 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
13600 AMOTION_EVENT_INVALID_CURSOR_POSITION},
13601 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
13602 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
13603 }
13604
13605 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Linnan Li13bf76a2024-05-05 19:18:02 +080013606 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013607 ui::LogicalDisplayId::INVALID,
Prabir Pradhan5735a322022-04-11 17:23:34 +000013608 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000013609 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013610 mPolicyFlags);
13611 }
13612
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013613 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000013614 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13615 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013616 sp<FakeWindowHandle> window =
13617 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, name,
13618 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013619 window->setOwnerInfo(mPid, mUid);
13620 return window;
13621 }
13622};
13623
13624using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
13625
13626TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013627 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013628 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013629 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013630
13631 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13632 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13633 window->consumeMotionDown();
13634
13635 setFocusedWindow(window);
13636 window->consumeFocusEvent(true);
13637
13638 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13639 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013640 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013641}
13642
13643TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013644 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013645 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013646 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013647
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013648 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013649 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13650 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13651
13652 setFocusedWindow(window);
13653 window->consumeFocusEvent(true);
13654
13655 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13656 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
13657 window->assertNoEvents();
13658}
13659
13660TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013661 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013662 auto window = owner.createWindow("Owned window");
13663 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013664 spy->setSpy(true);
13665 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013666 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013667
13668 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13669 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13670 spy->consumeMotionDown();
13671 window->consumeMotionDown();
13672}
13673
13674TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013675 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013676 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013677
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013678 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013679 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013680 randosSpy->setSpy(true);
13681 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013682 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013683
13684 // The event is targeted at owner's window, so injection should succeed, but the spy should
13685 // not receive the event.
13686 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13687 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13688 randosSpy->assertNoEvents();
13689 window->consumeMotionDown();
13690}
13691
13692TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013693 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013694 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013695
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013696 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013697 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013698 randosSpy->setSpy(true);
13699 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013700 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013701
13702 // A user that has injection permission can inject into any window.
13703 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013704 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013705 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan5735a322022-04-11 17:23:34 +000013706 randosSpy->consumeMotionDown();
13707 window->consumeMotionDown();
13708
13709 setFocusedWindow(randosSpy);
13710 randosSpy->consumeFocusEvent(true);
13711
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013712 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013713 randosSpy->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013714 window->assertNoEvents();
13715}
13716
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013717TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013718 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013719 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013720
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013721 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013722 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013723 randosWindow->setFrame(Rect{-10, -10, -5, -5});
13724 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013725 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013726
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013727 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000013728 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13729 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13730 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013731 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000013732}
13733
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013734using InputDispatcherPointerInWindowTest = InputDispatcherTest;
13735
13736TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
13737 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13738
13739 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013740 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013741 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013742 sp<FakeWindowHandle> right =
13743 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13744 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013745 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013746 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13747 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013748 spy->setFrame(Rect(0, 0, 200, 100));
13749 spy->setTrustedOverlay(true);
13750 spy->setSpy(true);
13751
13752 mDispatcher->onWindowInfosChanged(
13753 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13754
13755 // Hover into the left window.
13756 mDispatcher->notifyMotion(
13757 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
13758 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
13759 .build());
13760
13761 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13762 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13763
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013764 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13765 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013766 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013767 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13768 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013769 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013770 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13771 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013772 /*pointerId=*/0));
13773
13774 // Hover move to the right window.
13775 mDispatcher->notifyMotion(
13776 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
13777 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13778 .build());
13779
13780 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13781 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13782 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
13783
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013784 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13785 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013786 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013787 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13788 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013789 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013790 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13791 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013792 /*pointerId=*/0));
13793
13794 // Stop hovering.
13795 mDispatcher->notifyMotion(
13796 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
13797 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13798 .build());
13799
13800 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13801 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13802
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013803 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13804 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013805 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013806 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13807 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013808 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013809 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13810 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013811 /*pointerId=*/0));
13812}
13813
13814TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
13815 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13816
13817 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013818 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013819 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013820 sp<FakeWindowHandle> right =
13821 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13822 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013823 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013824 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13825 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013826 spy->setFrame(Rect(0, 0, 200, 100));
13827 spy->setTrustedOverlay(true);
13828 spy->setSpy(true);
13829
13830 mDispatcher->onWindowInfosChanged(
13831 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13832
13833 // First pointer down on left window.
13834 mDispatcher->notifyMotion(
13835 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13836 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13837 .build());
13838
13839 left->consumeMotionDown();
13840 spy->consumeMotionDown();
13841
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013842 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13843 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013844 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013845 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13846 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013847 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013848 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13849 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013850 /*pointerId=*/0));
13851
13852 // Second pointer down on right window.
13853 mDispatcher->notifyMotion(
13854 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13855 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13856 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13857 .build());
13858
13859 left->consumeMotionMove();
13860 right->consumeMotionDown();
13861 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
13862
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013863 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13864 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013865 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013866 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13867 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013868 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013869 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13870 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013871 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013872 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13873 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013874 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013875 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13876 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013877 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013878 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13879 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013880 /*pointerId=*/1));
13881
13882 // Second pointer up.
13883 mDispatcher->notifyMotion(
13884 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
13885 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13886 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13887 .build());
13888
13889 left->consumeMotionMove();
13890 right->consumeMotionUp();
13891 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
13892
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013893 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13894 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013895 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013896 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13897 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013898 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013899 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13900 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013901 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013902 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13903 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013904 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013905 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13906 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013907 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013908 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13909 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013910 /*pointerId=*/1));
13911
13912 // First pointer up.
13913 mDispatcher->notifyMotion(
13914 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
13915 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13916 .build());
13917
13918 left->consumeMotionUp();
13919 spy->consumeMotionUp();
13920
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013921 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13922 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013923 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013924 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13925 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013926 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013927 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13928 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013929 /*pointerId=*/0));
13930}
13931
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013932TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse_legacy) {
13933 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013934 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13935
13936 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013937 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013938 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013939 sp<FakeWindowHandle> right =
13940 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13941 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013942 right->setFrame(Rect(100, 0, 200, 100));
13943
13944 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
13945
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013946 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13947 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013948 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013949 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13950 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013951 /*pointerId=*/0));
13952
13953 // Hover move into the window.
13954 mDispatcher->notifyMotion(
13955 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13956 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
13957 .rawXCursorPosition(50)
13958 .rawYCursorPosition(50)
13959 .deviceId(DEVICE_ID)
13960 .build());
13961
13962 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13963
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013964 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13965 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013966 /*pointerId=*/0));
13967
13968 // Move the mouse with another device. This cancels the hovering pointer from the first device.
13969 mDispatcher->notifyMotion(
13970 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13971 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
13972 .rawXCursorPosition(51)
13973 .rawYCursorPosition(50)
13974 .deviceId(SECOND_DEVICE_ID)
13975 .build());
13976
13977 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13978 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13979
13980 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
13981 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013982 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13983 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013984 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013985 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013986 SECOND_DEVICE_ID,
13987 /*pointerId=*/0));
13988
13989 // Move the mouse outside the window. Document the current behavior, where the window does not
13990 // receive HOVER_EXIT even though the mouse left the window.
13991 mDispatcher->notifyMotion(
13992 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13993 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
13994 .rawXCursorPosition(150)
13995 .rawYCursorPosition(50)
13996 .deviceId(SECOND_DEVICE_ID)
13997 .build());
13998
13999 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14000 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014001 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14002 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014003 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014004 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014005 SECOND_DEVICE_ID,
14006 /*pointerId=*/0));
14007}
14008
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014009/**
14010 * TODO(b/313689709) - correctly support multiple mouse devices, because they should be controlling
14011 * the same cursor, and therefore have a shared motion event stream.
14012 */
14013TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
14014 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
14015 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14016
14017 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014018 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014019 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014020 sp<FakeWindowHandle> right =
14021 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14022 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014023 right->setFrame(Rect(100, 0, 200, 100));
14024
14025 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
14026
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014027 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14028 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014029 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014030 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14031 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014032 /*pointerId=*/0));
14033
14034 // Hover move into the window.
14035 mDispatcher->notifyMotion(
14036 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14037 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
14038 .rawXCursorPosition(50)
14039 .rawYCursorPosition(50)
14040 .deviceId(DEVICE_ID)
14041 .build());
14042
14043 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14044
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014045 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14046 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014047 /*pointerId=*/0));
14048
14049 // Move the mouse with another device
14050 mDispatcher->notifyMotion(
14051 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14052 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
14053 .rawXCursorPosition(51)
14054 .rawYCursorPosition(50)
14055 .deviceId(SECOND_DEVICE_ID)
14056 .build());
14057 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14058
14059 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
14060 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014061 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14062 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014063 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014064 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014065 SECOND_DEVICE_ID,
14066 /*pointerId=*/0));
14067
14068 // Move the mouse outside the window. Document the current behavior, where the window does not
14069 // receive HOVER_EXIT even though the mouse left the window.
14070 mDispatcher->notifyMotion(
14071 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14072 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
14073 .rawXCursorPosition(150)
14074 .rawYCursorPosition(50)
14075 .deviceId(SECOND_DEVICE_ID)
14076 .build());
14077
14078 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014079 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14080 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014081 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014082 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014083 SECOND_DEVICE_ID,
14084 /*pointerId=*/0));
14085}
14086
Arpit Singhb65e2bd2024-06-03 09:48:16 +000014087TEST_F(InputDispatcherTest, FocusedDisplayChangeIsNotified) {
14088 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
14089 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
14090}
14091
Garfield Tane84e6f92019-08-29 17:28:41 -070014092} // namespace android::inputdispatcher