blob: c70afd62b577497df282d0368612d430a2fc6718 [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 -0800414TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000415 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
416 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000417 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000418 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800419
420 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
421 args.policyFlags |= POLICY_FLAG_TRUSTED;
422 mFakePolicy->assertNotifySwitchWasCalled(args);
423}
424
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700425namespace {
426
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700427static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700428
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000429class FakeMonitorReceiver {
430public:
Linnan Li13bf76a2024-05-05 19:18:02 +0800431 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name,
432 ui::LogicalDisplayId displayId)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700433 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000434
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700435 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000436
Linnan Li13bf76a2024-05-05 19:18:02 +0800437 void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700438 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
439 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000440 }
441
442 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800443 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
444 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000445 }
446
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700447 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000448
Linnan Li13bf76a2024-05-05 19:18:02 +0800449 void consumeMotionDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700450 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
451 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000452 }
453
Linnan Li13bf76a2024-05-05 19:18:02 +0800454 void consumeMotionMove(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700455 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
456 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000457 }
458
Linnan Li13bf76a2024-05-05 19:18:02 +0800459 void consumeMotionUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700460 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
461 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000462 }
463
Linnan Li13bf76a2024-05-05 19:18:02 +0800464 void consumeMotionCancel(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700465 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000466 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
467 WithDisplayId(expectedDisplayId),
468 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
469 }
470
471 void consumeMotionPointerDown(int32_t pointerIdx) {
472 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
473 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700474 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700475 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000476 }
477
478 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700479 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000480 }
481
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800482 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000483
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800484 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000485
486private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700487 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000488};
489
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800490static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700491 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700492 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800493 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800494 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000495 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +0000496 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800497 KeyEvent event;
498 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
499
500 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800501 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +0000502 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
503 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800504
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800505 if (!allowKeyRepeat) {
506 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
507 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800508 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700509 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800510}
511
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700512static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
513 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700514 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
515 ui::LogicalDisplayId::INVALID, InputEventInjectionSync::WAIT_FOR_RESULT,
516 CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700517 if (result != InputEventInjectionResult::TIMED_OUT) {
518 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
519 }
520}
521
Linnan Li13bf76a2024-05-05 19:18:02 +0800522static InputEventInjectionResult injectKeyDown(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700523 InputDispatcher& dispatcher,
524 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000525 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700526}
527
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800528// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
529// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
530// has to be woken up to process the repeating key.
Linnan Li13bf76a2024-05-05 19:18:02 +0800531static InputEventInjectionResult injectKeyDownNoRepeat(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700532 InputDispatcher& dispatcher,
533 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000534 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800535 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +0000536 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800537}
538
Linnan Li13bf76a2024-05-05 19:18:02 +0800539static InputEventInjectionResult injectKeyUp(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700540 InputDispatcher& dispatcher,
541 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000542 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700543}
544
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800545static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700546 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -0700547 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000548 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000549 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700550 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
551 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -0700552}
553
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800554static InputEventInjectionResult injectMotionEvent(
Linnan Li13bf76a2024-05-05 19:18:02 +0800555 InputDispatcher& dispatcher, int32_t action, int32_t source, ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700556 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700557 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700558 AMOTION_EVENT_INVALID_CURSOR_POSITION},
559 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800560 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000561 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000562 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700563 MotionEventBuilder motionBuilder =
564 MotionEventBuilder(action, source)
565 .displayId(displayId)
566 .eventTime(eventTime)
567 .rawXCursorPosition(cursorPosition.x)
568 .rawYCursorPosition(cursorPosition.y)
569 .pointer(
570 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
571 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
572 motionBuilder.downTime(eventTime);
573 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800574
575 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700576 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
577 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800578}
579
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700580static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800581 ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700582 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700583 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -0700584}
585
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700586static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800587 ui::LogicalDisplayId displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800588 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700589 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +0000590}
591
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700592static NotifyKeyArgs generateKeyArgs(
593 int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Jackal Guof9696682018-10-05 12:23:23 +0800594 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
595 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000596 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
597 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
598 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800599
600 return args;
601}
602
Prabir Pradhan678438e2023-04-13 19:32:51 +0000603[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800604 ui::LogicalDisplayId displayId,
Prabir Pradhan678438e2023-04-13 19:32:51 +0000605 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -0800606 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700607 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
608 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
609 }
610
chaviwd1c23182019-12-20 18:44:56 -0800611 PointerProperties pointerProperties[pointerCount];
612 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800613
chaviwd1c23182019-12-20 18:44:56 -0800614 for (size_t i = 0; i < pointerCount; i++) {
615 pointerProperties[i].clear();
616 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -0700617 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800618
chaviwd1c23182019-12-20 18:44:56 -0800619 pointerCoords[i].clear();
620 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
621 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
622 }
Jackal Guof9696682018-10-05 12:23:23 +0800623
624 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
625 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000626 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
627 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
628 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800629 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000630 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700631 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000632 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +0800633
634 return args;
635}
636
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800637static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
638 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
639}
640
Linnan Li13bf76a2024-05-05 19:18:02 +0800641static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
642 ui::LogicalDisplayId displayId) {
chaviwd1c23182019-12-20 18:44:56 -0800643 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
644}
645
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000646static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
647 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000648 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
649 request);
Prabir Pradhan99987712020-11-10 18:43:05 -0800650}
651
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700652} // namespace
653
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800654/**
655 * When a window unexpectedly disposes of its input channel, policy should be notified about the
656 * broken channel.
657 */
658TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
659 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700660 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
661 "Window that breaks its input channel",
662 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800663
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700664 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800665
666 // Window closes its channel, but the window remains.
667 window->destroyReceiver();
668 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
669}
670
Arthur Hungb92218b2018-08-14 12:00:21 +0800671TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700672 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700673 sp<FakeWindowHandle> window =
674 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
675 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800676
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700677 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700679 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
680 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800681 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800682
683 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700684 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800685}
686
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800687using InputDispatcherDeathTest = InputDispatcherTest;
688
689/**
690 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
691 * should crash.
692 */
693TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
694 testing::GTEST_FLAG(death_test_style) = "threadsafe";
695 ScopedSilentDeath _silentDeath;
696
697 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700698 sp<FakeWindowHandle> window =
699 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
700 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800701 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
702 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
703 "Incorrect WindowInfosUpdate provided");
704}
705
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700706TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
707 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700708 sp<FakeWindowHandle> window =
709 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
710 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700711
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700712 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700713 // Inject a MotionEvent to an unknown display.
714 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700715 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
716 ui::LogicalDisplayId::INVALID))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700717 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
718
719 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700720 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700721}
722
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700723/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700724 * Calling onWindowInfosChanged once should not cause any issues.
725 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700726 * called twice.
727 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -0800728TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -0700729 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700730 sp<FakeWindowHandle> window =
731 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
732 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700733 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700734
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700735 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700737 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
738 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800739 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700740
741 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700742 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700743}
744
745/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700746 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700747 */
748TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700750 sp<FakeWindowHandle> window =
751 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
752 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700753 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700754
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700755 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
756 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800757 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700758 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
759 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800760 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700761
762 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700763 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700764}
765
Arthur Hungb92218b2018-08-14 12:00:21 +0800766// The foreground window should receive the first touch down event.
767TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700768 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700769 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
770 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000771 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700772 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
773 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800774
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700775 mDispatcher->onWindowInfosChanged(
776 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700778 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
779 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800780 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800781
782 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700783 windowTop->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800784 windowSecond->assertNoEvents();
785}
786
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000787/**
788 * Two windows: A top window, and a wallpaper behind the window.
789 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
790 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800791 * 1. foregroundWindow <-- dup touch to wallpaper
792 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000793 */
794TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
796 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700797 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
798 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800799 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000800 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700801 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
802 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800803 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000804
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700805 mDispatcher->onWindowInfosChanged(
806 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800808 injectMotionEvent(*mDispatcher,
809 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
810 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
811 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000812 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
813
814 // Both foreground window and its wallpaper should receive the touch down
815 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700816 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000817
818 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800819 injectMotionEvent(*mDispatcher,
820 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
821 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
822 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000823 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
824
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800825 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700826 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000827
828 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700829 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000830 foregroundWindow->consumeMotionCancel();
831 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700832 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000833}
834
835/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800836 * Two fingers down on the window, and lift off the first finger.
837 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
838 * contains a single pointer.
839 */
840TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
841 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700842 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
843 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800844
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700845 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800846 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +0000847 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
848 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
849 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800850 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000851 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
852 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
853 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
854 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800855 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000856 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
857 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
858 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
859 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800860 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
861 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
862 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
863
864 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700865 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800866 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
867 window->consumeMotionEvent(
868 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
869}
870
871/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800872 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
873 * with the following differences:
874 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
875 * clean up the connection.
876 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
877 * Ensure that there's no crash in the dispatcher.
878 */
879TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
880 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
881 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700882 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
883 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800884 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800885 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700886 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
887 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800888 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800889
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700890 mDispatcher->onWindowInfosChanged(
891 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800892 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700893 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
894 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800895 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
896
897 // Both foreground window and its wallpaper should receive the touch down
898 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700899 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800900
901 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700902 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700903 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800904 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
905
906 foregroundWindow->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700907 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800908
909 // Wallpaper closes its channel, but the window remains.
910 wallpaperWindow->destroyReceiver();
911 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
912
913 // Now the foreground window goes away, but the wallpaper stays, even though its channel
914 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700915 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800916 foregroundWindow->consumeMotionCancel();
917}
918
Linnan Li72352222024-04-12 18:55:57 +0800919/**
920 * Two windows: left and right, and a separate wallpaper window underneath each. Device A sends a
921 * down event to the left window. Device B sends a down event to the right window. Next, the right
922 * window disappears. Both the right window and its wallpaper window should receive cancel event.
923 * The left window and its wallpaper window should not receive any events.
924 */
925TEST_F(InputDispatcherTest, MultiDeviceDisappearingWindowWithWallpaperWindows) {
926 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
927 sp<FakeWindowHandle> leftForegroundWindow =
928 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700929 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800930 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
931 leftForegroundWindow->setDupTouchToWallpaper(true);
932 sp<FakeWindowHandle> leftWallpaperWindow =
933 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700934 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800935 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
936 leftWallpaperWindow->setIsWallpaper(true);
937
938 sp<FakeWindowHandle> rightForegroundWindow =
939 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700940 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800941 rightForegroundWindow->setFrame(Rect(100, 0, 200, 100));
942 rightForegroundWindow->setDupTouchToWallpaper(true);
943 sp<FakeWindowHandle> rightWallpaperWindow =
944 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700945 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800946 rightWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
947 rightWallpaperWindow->setIsWallpaper(true);
948
949 mDispatcher->onWindowInfosChanged(
950 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
951 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
952 {},
953 0,
954 0});
955
956 const DeviceId deviceA = 9;
957 const DeviceId deviceB = 3;
958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
959 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
960 .deviceId(deviceA)
961 .build());
962 leftForegroundWindow->consumeMotionEvent(
963 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
964 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
965 WithDeviceId(deviceA),
966 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
967
968 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
969 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
970 .deviceId(deviceB)
971 .build());
972 rightForegroundWindow->consumeMotionEvent(
973 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
974 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
975 WithDeviceId(deviceB),
976 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
977
978 // Now right foreground window disappears, but right wallpaper window remains.
979 mDispatcher->onWindowInfosChanged(
980 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
981 *rightWallpaperWindow->getInfo()},
982 {},
983 0,
984 0});
985
986 // Left foreground window and left wallpaper window still exist, and should not receive any
987 // events.
988 leftForegroundWindow->assertNoEvents();
989 leftWallpaperWindow->assertNoEvents();
990 // Since right foreground window disappeared, right wallpaper window and right foreground window
991 // should receive cancel events.
992 rightForegroundWindow->consumeMotionEvent(
993 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
994 rightWallpaperWindow->consumeMotionEvent(
995 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
996 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
997}
998
999/**
1000 * Three windows arranged horizontally and without any overlap. Every window has a
1001 * wallpaper window underneath. The middle window also has SLIPPERY flag.
1002 * Device A sends a down event to the left window. Device B sends a down event to the middle window.
1003 * Next, device B sends move event to the right window. Touch for device B should slip from the
1004 * middle window to the right window. Also, the right wallpaper window should receive a down event.
1005 * The middle window and its wallpaper window should receive a cancel event. The left window should
1006 * not receive any events. If device B continues to report events, the right window and its
1007 * wallpaper window should receive remaining events.
1008 */
1009TEST_F(InputDispatcherTest, MultiDeviceSlipperyTouchWithWallpaperWindow) {
1010 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1011 sp<FakeWindowHandle> leftForegroundWindow =
1012 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001013 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001014 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1015 leftForegroundWindow->setDupTouchToWallpaper(true);
1016 sp<FakeWindowHandle> leftWallpaperWindow =
1017 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001018 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001019 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1020 leftWallpaperWindow->setIsWallpaper(true);
1021
1022 sp<FakeWindowHandle> middleForegroundWindow =
1023 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001024 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001025 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1026 middleForegroundWindow->setDupTouchToWallpaper(true);
1027 middleForegroundWindow->setSlippery(true);
1028 sp<FakeWindowHandle> middleWallpaperWindow =
1029 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001030 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001031 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1032 middleWallpaperWindow->setIsWallpaper(true);
1033
1034 sp<FakeWindowHandle> rightForegroundWindow =
1035 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001036 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001037 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1038 rightForegroundWindow->setDupTouchToWallpaper(true);
1039 sp<FakeWindowHandle> rightWallpaperWindow =
1040 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001041 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001042 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1043 rightWallpaperWindow->setIsWallpaper(true);
1044
1045 mDispatcher->onWindowInfosChanged(
1046 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1047 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1048 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1049 {},
1050 0,
1051 0});
1052
1053 const DeviceId deviceA = 9;
1054 const DeviceId deviceB = 3;
1055 // Device A sends a DOWN event to the left window
1056 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1057 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1058 .deviceId(deviceA)
1059 .build());
1060 leftForegroundWindow->consumeMotionEvent(
1061 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1062 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1063 WithDeviceId(deviceA),
1064 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1065 // Device B sends a DOWN event to the middle window
1066 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1067 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1068 .deviceId(deviceB)
1069 .build());
1070 middleForegroundWindow->consumeMotionEvent(
1071 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1072 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1073 WithDeviceId(deviceB),
1074 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1075 // Move the events of device B to the top of the right window.
1076 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1077 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
1078 .deviceId(deviceB)
1079 .build());
1080 middleForegroundWindow->consumeMotionEvent(
1081 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1082 middleWallpaperWindow->consumeMotionEvent(
1083 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1084 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1085 rightForegroundWindow->consumeMotionEvent(
1086 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1087 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1088 WithDeviceId(deviceB),
1089 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1090 // Make sure the window on the right can receive the remaining events.
1091 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1092 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1093 .deviceId(deviceB)
1094 .build());
1095 leftForegroundWindow->assertNoEvents();
1096 leftWallpaperWindow->assertNoEvents();
1097 middleForegroundWindow->assertNoEvents();
1098 middleWallpaperWindow->assertNoEvents();
1099 rightForegroundWindow->consumeMotionEvent(
1100 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
1101 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1102 WithDeviceId(deviceB),
1103 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1104}
1105
1106/**
1107 * Similar to the test above, we have three windows, they are arranged horizontally and without any
1108 * overlap, and every window has a wallpaper window. The middle window is a simple window, without
1109 * any special flags. Device A reports a down event that lands in left window. Device B sends a down
1110 * event to the middle window and then touch is transferred from the middle window to the right
1111 * window. The right window and its wallpaper window should receive a down event. The middle window
1112 * and its wallpaper window should receive a cancel event. The left window should not receive any
1113 * events. Subsequent events reported by device B should go to the right window and its wallpaper.
1114 */
1115TEST_F(InputDispatcherTest, MultiDeviceTouchTransferWithWallpaperWindows) {
1116 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1117 sp<FakeWindowHandle> leftForegroundWindow =
1118 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001119 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001120 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1121 leftForegroundWindow->setDupTouchToWallpaper(true);
1122 sp<FakeWindowHandle> leftWallpaperWindow =
1123 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001124 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001125 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1126 leftWallpaperWindow->setIsWallpaper(true);
1127
1128 sp<FakeWindowHandle> middleForegroundWindow =
1129 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001130 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001131 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1132 middleForegroundWindow->setDupTouchToWallpaper(true);
1133 sp<FakeWindowHandle> middleWallpaperWindow =
1134 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001135 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001136 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1137 middleWallpaperWindow->setIsWallpaper(true);
1138
1139 sp<FakeWindowHandle> rightForegroundWindow =
1140 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001141 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001142 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1143 rightForegroundWindow->setDupTouchToWallpaper(true);
1144 sp<FakeWindowHandle> rightWallpaperWindow =
1145 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001146 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001147 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1148 rightWallpaperWindow->setIsWallpaper(true);
1149
1150 mDispatcher->onWindowInfosChanged(
1151 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1152 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1153 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1154 {},
1155 0,
1156 0});
1157
1158 const DeviceId deviceA = 9;
1159 const DeviceId deviceB = 3;
1160 // Device A touch down on the left window
1161 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1162 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1163 .deviceId(deviceA)
1164 .build());
1165 leftForegroundWindow->consumeMotionEvent(
1166 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1167 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1168 WithDeviceId(deviceA),
1169 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1170 // Device B touch down on the middle window
1171 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1172 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1173 .deviceId(deviceB)
1174 .build());
1175 middleForegroundWindow->consumeMotionEvent(
1176 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1177 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1178 WithDeviceId(deviceB),
1179 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1180
1181 // Transfer touch from the middle window to the right window.
1182 ASSERT_TRUE(mDispatcher->transferTouchGesture(middleForegroundWindow->getToken(),
1183 rightForegroundWindow->getToken()));
1184
1185 middleForegroundWindow->consumeMotionEvent(
1186 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1187 middleWallpaperWindow->consumeMotionEvent(
1188 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1189 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1190 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1191 WithDeviceId(deviceB),
1192 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1193 rightWallpaperWindow->consumeMotionEvent(
1194 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
1195 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1196
1197 // Make sure the right window can receive the remaining events.
1198 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1199 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1200 .deviceId(deviceB)
1201 .build());
1202 leftForegroundWindow->assertNoEvents();
1203 leftWallpaperWindow->assertNoEvents();
1204 middleForegroundWindow->assertNoEvents();
1205 middleWallpaperWindow->assertNoEvents();
1206 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1207 WithDeviceId(deviceB),
1208 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1209 rightWallpaperWindow->consumeMotionEvent(
1210 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB),
1211 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1212}
1213
Arthur Hungc539dbb2022-12-08 07:45:36 +00001214class ShouldSplitTouchFixture : public InputDispatcherTest,
1215 public ::testing::WithParamInterface<bool> {};
1216INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1217 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001218/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001219 * A single window that receives touch (on top), and a wallpaper window underneath it.
1220 * The top window gets a multitouch gesture.
1221 * Ensure that wallpaper gets the same gesture.
1222 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001223TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001224 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001225 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001226 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
1227 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001228 foregroundWindow->setDupTouchToWallpaper(true);
1229 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001230
1231 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001232 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1233 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001234 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001235
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001236 mDispatcher->onWindowInfosChanged(
1237 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001238
1239 // Touch down on top window
1240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001241 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1242 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001243 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1244
1245 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001246 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001247 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001248
1249 // Second finger down on the top window
1250 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001251 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001252 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001253 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1254 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001255 .build();
1256 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001257 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001258 InputEventInjectionSync::WAIT_FOR_RESULT))
1259 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00001260 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001261 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001262 EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001263
1264 const MotionEvent secondFingerUpEvent =
1265 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001266 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hungc539dbb2022-12-08 07:45:36 +00001267 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001268 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1269 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001270 .build();
1271 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001272 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001273 InputEventInjectionSync::WAIT_FOR_RESULT))
1274 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00001275 foregroundWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1276 WithDisplayId(ui::LogicalDisplayId::DEFAULT));
1277 wallpaperWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1278 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
1279 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
Arthur Hungc539dbb2022-12-08 07:45:36 +00001280
1281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001282 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001283 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1284 AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001285 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001286 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001287 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001288 .x(100)
1289 .y(100))
1290 .build(),
1291 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001292 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001293 foregroundWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
1294 wallpaperWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001295}
1296
1297/**
1298 * Two windows: a window on the left and window on the right.
1299 * A third window, wallpaper, is behind both windows, and spans both top windows.
1300 * The first touch down goes to the left window. A second pointer touches down on the right window.
1301 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1302 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1303 * ACTION_POINTER_DOWN(1).
1304 */
1305TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1306 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001307 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1308 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001309 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001310 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001311
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001312 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1313 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001314 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001315 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001316
1317 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001318 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1319 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001320 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001321 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001322
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001323 mDispatcher->onWindowInfosChanged(
1324 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1325 {},
1326 0,
1327 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001328
1329 // Touch down on left window
1330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001331 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1332 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001333 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1334
1335 // Both foreground window and its wallpaper should receive the touch down
1336 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001337 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001338
1339 // Second finger down on the right window
1340 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001341 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001342 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001343 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1344 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001345 .build();
1346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001347 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001348 InputEventInjectionSync::WAIT_FOR_RESULT))
1349 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1350
1351 leftWindow->consumeMotionMove();
1352 // Since the touch is split, right window gets ACTION_DOWN
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001353 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1354 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001355 EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001356
1357 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001358 mDispatcher->onWindowInfosChanged(
1359 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001360 leftWindow->consumeMotionCancel();
1361 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001362 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001363
1364 // The pointer that's still down on the right window moves, and goes to the right window only.
1365 // As far as the dispatcher's concerned though, both pointers are still present.
1366 const MotionEvent secondFingerMoveEvent =
1367 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1368 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001369 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1370 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001371 .build();
1372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001373 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001374 InputEventInjectionSync::WAIT_FOR_RESULT));
1375 rightWindow->consumeMotionMove();
1376
1377 leftWindow->assertNoEvents();
1378 rightWindow->assertNoEvents();
1379 wallpaperWindow->assertNoEvents();
1380}
1381
Arthur Hungc539dbb2022-12-08 07:45:36 +00001382/**
1383 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
1384 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
1385 * The right window should receive ACTION_DOWN.
1386 */
1387TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00001388 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001389 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1390 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001391 leftWindow->setFrame(Rect(0, 0, 200, 200));
1392 leftWindow->setDupTouchToWallpaper(true);
1393 leftWindow->setSlippery(true);
1394
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001395 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1396 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001397 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00001398
1399 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001400 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1401 ui::LogicalDisplayId::DEFAULT);
Arthur Hung74c248d2022-11-23 07:09:59 +00001402 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00001403
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001404 mDispatcher->onWindowInfosChanged(
1405 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1406 {},
1407 0,
1408 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00001409
Arthur Hungc539dbb2022-12-08 07:45:36 +00001410 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00001411 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001412 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1413 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001414 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00001415
1416 // Both foreground window and its wallpaper should receive the touch down
1417 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001418 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001419
Arthur Hungc539dbb2022-12-08 07:45:36 +00001420 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00001421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001422 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001423 ui::LogicalDisplayId::DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001424 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1425
Arthur Hungc539dbb2022-12-08 07:45:36 +00001426 leftWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001427 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1428 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001429}
1430
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001431/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001432 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1433 * interactive, it might stop sending this flag.
1434 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
1435 * to have a consistent input stream.
1436 *
1437 * Test procedure:
1438 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
1439 * DOWN (new gesture).
1440 *
1441 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
1442 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
1443 *
1444 * We technically just need a single window here, but we are using two windows (spy on top and a
1445 * regular window below) to emulate the actual situation where it happens on the device.
1446 */
1447TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
1448 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001449 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
1450 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001451 spyWindow->setFrame(Rect(0, 0, 200, 200));
1452 spyWindow->setTrustedOverlay(true);
1453 spyWindow->setSpy(true);
1454
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001455 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1456 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001457 window->setFrame(Rect(0, 0, 200, 200));
1458
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001459 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001460 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001461
1462 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001463 mDispatcher->notifyMotion(
1464 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1465 .deviceId(touchDeviceId)
1466 .policyFlags(DEFAULT_POLICY_FLAGS)
1467 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1468 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001469
Prabir Pradhan678438e2023-04-13 19:32:51 +00001470 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1471 .deviceId(touchDeviceId)
1472 .policyFlags(DEFAULT_POLICY_FLAGS)
1473 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1474 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1475 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001476 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1477 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1478 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1479 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1480
1481 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001482 mDispatcher->notifyMotion(
1483 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
1484 .deviceId(touchDeviceId)
1485 .policyFlags(0)
1486 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1487 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1488 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001489 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1490 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1491
1492 // We don't need to reset the device to reproduce the issue, but the reset event typically
1493 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001494 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001495
1496 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00001497 mDispatcher->notifyMotion(
1498 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1499 .deviceId(touchDeviceId)
1500 .policyFlags(DEFAULT_POLICY_FLAGS)
1501 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1502 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001503 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1504 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1505
1506 // No more events
1507 spyWindow->assertNoEvents();
1508 window->assertNoEvents();
1509}
1510
1511/**
Linnan Li907ae732023-09-05 17:14:21 +08001512 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
1513 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1514 * interactive, it might stop sending this flag.
1515 * We've already ensured the consistency of the touch event in this case, and we should also ensure
1516 * the consistency of the hover event in this case.
1517 *
1518 * Test procedure:
1519 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
1520 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
1521 *
1522 * We expect to receive two full streams of hover events.
1523 */
1524TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
1525 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1526
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001527 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1528 ui::LogicalDisplayId::DEFAULT);
Linnan Li907ae732023-09-05 17:14:21 +08001529 window->setFrame(Rect(0, 0, 300, 300));
1530
1531 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1532
1533 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1534 .policyFlags(DEFAULT_POLICY_FLAGS)
1535 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
1536 .build());
1537 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1538
1539 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1540 .policyFlags(DEFAULT_POLICY_FLAGS)
1541 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1542 .build());
1543 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1544
1545 // Send hover exit without the default policy flags.
1546 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1547 .policyFlags(0)
1548 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1549 .build());
1550
1551 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1552
1553 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
1554 // right event.
1555 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1556 .policyFlags(DEFAULT_POLICY_FLAGS)
1557 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
1558 .build());
1559 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1560
1561 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1562 .policyFlags(DEFAULT_POLICY_FLAGS)
1563 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1564 .build());
1565 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1566
1567 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1568 .policyFlags(DEFAULT_POLICY_FLAGS)
1569 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1570 .build());
1571 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1572}
1573
1574/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001575 * Two windows: a window on the left and a window on the right.
1576 * Mouse is hovered from the right window into the left window.
1577 * Next, we tap on the left window, where the cursor was last seen.
1578 * The second tap is done onto the right window.
1579 * The mouse and tap are from two different devices.
1580 * We technically don't need to set the downtime / eventtime for these events, but setting these
1581 * explicitly helps during debugging.
1582 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1583 * In the buggy implementation, a tap on the right window would cause a crash.
1584 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001585TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap_legacy) {
1586 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
1587
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001588 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001589 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1590 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001591 leftWindow->setFrame(Rect(0, 0, 200, 200));
1592
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001593 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1594 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001595 rightWindow->setFrame(Rect(200, 0, 400, 200));
1596
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001597 mDispatcher->onWindowInfosChanged(
1598 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001599 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1600 // stale.
1601 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1602 const int32_t mouseDeviceId = 6;
1603 const int32_t touchDeviceId = 4;
1604 // Move the cursor from right
1605 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001606 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001607 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1608 AINPUT_SOURCE_MOUSE)
1609 .deviceId(mouseDeviceId)
1610 .downTime(baseTime + 10)
1611 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001612 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001613 .build()));
1614 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1615
1616 // .. to the left window
1617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001618 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001619 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1620 AINPUT_SOURCE_MOUSE)
1621 .deviceId(mouseDeviceId)
1622 .downTime(baseTime + 10)
1623 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001624 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001625 .build()));
1626 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1627 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1628 // Now tap the left window
1629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001630 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001631 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1632 AINPUT_SOURCE_TOUCHSCREEN)
1633 .deviceId(touchDeviceId)
1634 .downTime(baseTime + 40)
1635 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001636 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001637 .build()));
1638 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1639 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1640
1641 // release tap
1642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001643 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001644 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1645 AINPUT_SOURCE_TOUCHSCREEN)
1646 .deviceId(touchDeviceId)
1647 .downTime(baseTime + 40)
1648 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001649 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001650 .build()));
1651 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1652
1653 // Tap the window on the right
1654 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001655 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001656 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1657 AINPUT_SOURCE_TOUCHSCREEN)
1658 .deviceId(touchDeviceId)
1659 .downTime(baseTime + 60)
1660 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001661 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001662 .build()));
1663 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1664
1665 // release tap
1666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001667 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001668 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1669 AINPUT_SOURCE_TOUCHSCREEN)
1670 .deviceId(touchDeviceId)
1671 .downTime(baseTime + 60)
1672 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001673 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001674 .build()));
1675 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1676
1677 // No more events
1678 leftWindow->assertNoEvents();
1679 rightWindow->assertNoEvents();
1680}
1681
1682/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001683 * Two windows: a window on the left and a window on the right.
1684 * Mouse is hovered from the right window into the left window.
1685 * Next, we tap on the left window, where the cursor was last seen.
1686 * The second tap is done onto the right window.
1687 * The mouse and tap are from two different devices.
1688 * We technically don't need to set the downtime / eventtime for these events, but setting these
1689 * explicitly helps during debugging.
1690 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1691 * In the buggy implementation, a tap on the right window would cause a crash.
1692 */
1693TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
1694 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1695
1696 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001697 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1698 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001699 leftWindow->setFrame(Rect(0, 0, 200, 200));
1700
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001701 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1702 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001703 rightWindow->setFrame(Rect(200, 0, 400, 200));
1704
1705 mDispatcher->onWindowInfosChanged(
1706 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
1707 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1708 // stale.
1709 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1710 const int32_t mouseDeviceId = 6;
1711 const int32_t touchDeviceId = 4;
1712 // Move the cursor from right
1713 mDispatcher->notifyMotion(
1714 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1715 .deviceId(mouseDeviceId)
1716 .downTime(baseTime + 10)
1717 .eventTime(baseTime + 20)
1718 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
1719 .build());
1720 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1721
1722 // .. to the left window
1723 mDispatcher->notifyMotion(
1724 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1725 .deviceId(mouseDeviceId)
1726 .downTime(baseTime + 10)
1727 .eventTime(baseTime + 30)
1728 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
1729 .build());
1730 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1731 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1732 // Now tap the left window
1733 mDispatcher->notifyMotion(
1734 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1735 .deviceId(touchDeviceId)
1736 .downTime(baseTime + 40)
1737 .eventTime(baseTime + 40)
1738 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1739 .build());
1740 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1741
1742 // release tap
1743 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1744 .deviceId(touchDeviceId)
1745 .downTime(baseTime + 40)
1746 .eventTime(baseTime + 50)
1747 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1748 .build());
1749 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1750
1751 // Tap the window on the right
1752 mDispatcher->notifyMotion(
1753 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1754 .deviceId(touchDeviceId)
1755 .downTime(baseTime + 60)
1756 .eventTime(baseTime + 60)
1757 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1758 .build());
1759 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1760
1761 // release tap
1762 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1763 .deviceId(touchDeviceId)
1764 .downTime(baseTime + 60)
1765 .eventTime(baseTime + 70)
1766 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1767 .build());
1768 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1769
1770 // No more events
1771 leftWindow->assertNoEvents();
1772 rightWindow->assertNoEvents();
1773}
1774
1775/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001776 * Start hovering in a window. While this hover is still active, make another window appear on top.
1777 * The top, obstructing window has no input channel, so it's not supposed to receive input.
1778 * While the top window is present, the hovering is stopped.
1779 * Later, hovering gets resumed again.
1780 * Ensure that new hover gesture is handled correctly.
1781 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
1782 * to the window that's currently being hovered over.
1783 */
1784TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
1785 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001786 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1787 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001788 window->setFrame(Rect(0, 0, 200, 200));
1789
1790 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001791 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001792
1793 // Start hovering in the window
1794 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1795 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1796 .build());
1797 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1798
1799 // Now, an obscuring window appears!
1800 sp<FakeWindowHandle> obscuringWindow =
1801 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001802 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001803 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001804 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1805 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1806 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1807 obscuringWindow->setNoInputChannel(true);
1808 obscuringWindow->setFocusable(false);
1809 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001810 mDispatcher->onWindowInfosChanged(
1811 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001812
1813 // While this new obscuring window is present, the hovering is stopped
1814 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1815 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1816 .build());
1817 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1818
1819 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001820 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001821
1822 // And a new hover gesture starts.
1823 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1824 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1825 .build());
1826 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1827}
1828
1829/**
1830 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
1831 * the obscuring window.
1832 */
1833TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
1834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001835 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1836 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001837 window->setFrame(Rect(0, 0, 200, 200));
1838
1839 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001840 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001841
1842 // Start hovering in the window
1843 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1844 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1845 .build());
1846 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1847
1848 // Now, an obscuring window appears!
1849 sp<FakeWindowHandle> obscuringWindow =
1850 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001851 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001852 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001853 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1854 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1855 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1856 obscuringWindow->setNoInputChannel(true);
1857 obscuringWindow->setFocusable(false);
1858 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001859 mDispatcher->onWindowInfosChanged(
1860 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001861
1862 // While this new obscuring window is present, the hovering continues. The event can't go to the
1863 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
1864 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1865 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1866 .build());
1867 obscuringWindow->assertNoEvents();
1868 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1869
1870 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001871 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001872
1873 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
1874 // so it should generate a HOVER_ENTER
1875 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1876 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1877 .build());
1878 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1879
1880 // Now the MOVE should be getting dispatched normally
1881 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1882 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
1883 .build());
1884 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1885}
1886
1887/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001888 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
1889 * events are delivered to the window.
1890 */
1891TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
1892 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001893 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1894 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001895 window->setFrame(Rect(0, 0, 200, 200));
1896 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1897
1898 // Start hovering in the window
1899 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
1900 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1901 .build());
1902 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1903
1904 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1905 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1906 .build());
1907 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1908
1909 // Scroll with the mouse
1910 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
1911 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1912 .build());
1913 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
1914}
1915
1916using InputDispatcherMultiDeviceTest = InputDispatcherTest;
1917
1918/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001919 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
1920 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001921 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001922TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001923 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001924 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001925 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1926 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001927 window->setFrame(Rect(0, 0, 200, 200));
1928
1929 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1930
1931 constexpr int32_t touchDeviceId = 4;
1932 constexpr int32_t stylusDeviceId = 2;
1933
1934 // Stylus down
1935 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1936 .deviceId(stylusDeviceId)
1937 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
1938 .build());
1939 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
1940
1941 // Touch down
1942 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1943 .deviceId(touchDeviceId)
1944 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
1945 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001946
1947 // Touch move
1948 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1949 .deviceId(touchDeviceId)
1950 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
1951 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001952 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001953
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001954 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001955 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
1956 .deviceId(stylusDeviceId)
1957 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
1958 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001959 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
1960 WithCoords(101, 111)));
1961
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001962 window->assertNoEvents();
1963}
1964
1965/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001966 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
1967 * touch is not dropped, because multiple devices are allowed to be active in the same window.
1968 */
1969TEST_F(InputDispatcherMultiDeviceTest, StylusDownDoesNotBlockTouchDown) {
1970 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1971 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001972 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1973 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001974 window->setFrame(Rect(0, 0, 200, 200));
1975
1976 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1977
1978 constexpr int32_t touchDeviceId = 4;
1979 constexpr int32_t stylusDeviceId = 2;
1980
1981 // Stylus down
1982 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1983 .deviceId(stylusDeviceId)
1984 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
1985 .build());
1986 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
1987
1988 // Touch down
1989 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1990 .deviceId(touchDeviceId)
1991 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
1992 .build());
1993 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
1994
1995 // Touch move
1996 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1997 .deviceId(touchDeviceId)
1998 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
1999 .build());
2000 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2001
2002 // Stylus move
2003 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2004 .deviceId(stylusDeviceId)
2005 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2006 .build());
2007 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2008 WithCoords(101, 111)));
2009
2010 window->assertNoEvents();
2011}
2012
2013/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002014 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002015 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002016 * Similar test as above, but with added SPY window.
2017 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002018TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002019 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002020 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002021 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2022 ui::LogicalDisplayId::DEFAULT);
2023 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2024 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002025 spyWindow->setFrame(Rect(0, 0, 200, 200));
2026 spyWindow->setTrustedOverlay(true);
2027 spyWindow->setSpy(true);
2028 window->setFrame(Rect(0, 0, 200, 200));
2029
2030 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2031
2032 constexpr int32_t touchDeviceId = 4;
2033 constexpr int32_t stylusDeviceId = 2;
2034
2035 // Stylus down
2036 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2037 .deviceId(stylusDeviceId)
2038 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2039 .build());
2040 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2041 spyWindow->consumeMotionEvent(
2042 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2043
2044 // Touch down
2045 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2046 .deviceId(touchDeviceId)
2047 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2048 .build());
2049
2050 // Touch move
2051 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2052 .deviceId(touchDeviceId)
2053 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2054 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002055
2056 // Touch is ignored because stylus is already down
2057
2058 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002059 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2060 .deviceId(stylusDeviceId)
2061 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2062 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002063 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2064 WithCoords(101, 111)));
2065 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2066 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002067
2068 window->assertNoEvents();
2069 spyWindow->assertNoEvents();
2070}
2071
2072/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002073 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2074 * down. Ensure that touch is not dropped, because multiple devices can be active at the same time.
2075 * Similar test as above, but with added SPY window.
2076 */
2077TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyDoesNotBlockTouchDown) {
2078 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2079 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002080 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2081 ui::LogicalDisplayId::DEFAULT);
2082 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2083 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002084 spyWindow->setFrame(Rect(0, 0, 200, 200));
2085 spyWindow->setTrustedOverlay(true);
2086 spyWindow->setSpy(true);
2087 window->setFrame(Rect(0, 0, 200, 200));
2088
2089 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2090
2091 constexpr int32_t touchDeviceId = 4;
2092 constexpr int32_t stylusDeviceId = 2;
2093
2094 // Stylus down
2095 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2096 .deviceId(stylusDeviceId)
2097 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2098 .build());
2099 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2100 spyWindow->consumeMotionEvent(
2101 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2102
2103 // Touch down
2104 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2105 .deviceId(touchDeviceId)
2106 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2107 .build());
2108 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2109 spyWindow->consumeMotionEvent(
2110 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2111
2112 // Touch move
2113 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2114 .deviceId(touchDeviceId)
2115 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2116 .build());
2117 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2118 spyWindow->consumeMotionEvent(
2119 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2120
2121 // Subsequent stylus movements are delivered correctly
2122 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2123 .deviceId(stylusDeviceId)
2124 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2125 .build());
2126 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2127 WithCoords(101, 111)));
2128 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2129 WithCoords(101, 111)));
2130
2131 window->assertNoEvents();
2132 spyWindow->assertNoEvents();
2133}
2134
2135/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002136 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002137 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002138 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002139TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002140 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002141 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002142 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2143 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002144 window->setFrame(Rect(0, 0, 200, 200));
2145
2146 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2147
2148 constexpr int32_t touchDeviceId = 4;
2149 constexpr int32_t stylusDeviceId = 2;
2150
2151 // Stylus down on the window
2152 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2153 .deviceId(stylusDeviceId)
2154 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2155 .build());
2156 window->consumeMotionEvent(
2157 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2158
2159 // Touch down on window
2160 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2161 .deviceId(touchDeviceId)
2162 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2163 .build());
2164 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2165 .deviceId(touchDeviceId)
2166 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2167 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002168
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002169 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002170
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002171 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002172 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2173 .deviceId(stylusDeviceId)
2174 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2175 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002176 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2177 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002178
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002179 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002180 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2181 .deviceId(touchDeviceId)
2182 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2183 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002184 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002185}
2186
2187/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002188 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2189 * touch is not dropped, because stylus hover and touch can be both active at the same time.
2190 */
2191TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
2192 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2193 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002194 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2195 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002196 window->setFrame(Rect(0, 0, 200, 200));
2197
2198 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2199
2200 constexpr int32_t touchDeviceId = 4;
2201 constexpr int32_t stylusDeviceId = 2;
2202
2203 // Stylus down on the window
2204 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2205 .deviceId(stylusDeviceId)
2206 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2207 .build());
2208 window->consumeMotionEvent(
2209 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2210
2211 // Touch down on window
2212 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2213 .deviceId(touchDeviceId)
2214 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2215 .build());
2216 // Touch move on window
2217 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2218 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2219 .deviceId(touchDeviceId)
2220 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2221 .build());
2222 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2223
2224 // Subsequent stylus movements are delivered correctly
2225 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2226 .deviceId(stylusDeviceId)
2227 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2228 .build());
2229 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2230 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2231
2232 // and subsequent touches continue to work
2233 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2234 .deviceId(touchDeviceId)
2235 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2236 .build());
2237 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2238 window->assertNoEvents();
2239}
2240
2241/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002242 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002243 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002244 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002245TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002246 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002247 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002248 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2249 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002250 window->setFrame(Rect(0, 0, 200, 200));
2251
2252 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2253
2254 constexpr int32_t touchDeviceId = 4;
2255 constexpr int32_t stylusDeviceId = 2;
2256
2257 // Touch down on window
2258 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2259 .deviceId(touchDeviceId)
2260 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2261 .build());
2262 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2263 .deviceId(touchDeviceId)
2264 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2265 .build());
2266 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2267 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2268
2269 // Stylus hover on the window
2270 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2271 .deviceId(stylusDeviceId)
2272 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2273 .build());
2274 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2275 .deviceId(stylusDeviceId)
2276 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2277 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002278 // Stylus hover movement causes touch to be canceled
2279 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2280 WithCoords(141, 146)));
2281 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2282 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2283 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2284 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002285
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002286 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002287 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2288 .deviceId(touchDeviceId)
2289 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2290 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002291
2292 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002293}
2294
2295/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002296 * One window. Touch down on the window. Then, stylus hover on the window from another device.
2297 * Ensure that touch is not canceled, because stylus hover can be active at the same time as touch.
2298 */
2299TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2300 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2301 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002302 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2303 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002304 window->setFrame(Rect(0, 0, 200, 200));
2305
2306 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2307
2308 constexpr int32_t touchDeviceId = 4;
2309 constexpr int32_t stylusDeviceId = 2;
2310
2311 // Touch down on window
2312 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2313 .deviceId(touchDeviceId)
2314 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2315 .build());
2316 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2317 .deviceId(touchDeviceId)
2318 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2319 .build());
2320 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2321 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2322
2323 // Stylus hover on the window
2324 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2325 .deviceId(stylusDeviceId)
2326 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2327 .build());
2328 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2329 .deviceId(stylusDeviceId)
2330 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2331 .build());
2332 // Stylus hover movement is received normally
2333 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2334 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2335 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2336 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2337
2338 // Subsequent touch movements also work
2339 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2340 .deviceId(touchDeviceId)
2341 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2342 .build());
2343 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2344 WithCoords(142, 147)));
2345
2346 window->assertNoEvents();
2347}
2348
2349/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002350 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2351 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2352 * become active.
2353 */
2354TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002355 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002356 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002357 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2358 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002359 window->setFrame(Rect(0, 0, 200, 200));
2360
2361 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2362
2363 constexpr int32_t stylusDeviceId1 = 3;
2364 constexpr int32_t stylusDeviceId2 = 5;
2365
2366 // Touch down on window
2367 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2368 .deviceId(stylusDeviceId1)
2369 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2370 .build());
2371 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2372 .deviceId(stylusDeviceId1)
2373 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2374 .build());
2375 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2376 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2377
2378 // Second stylus down
2379 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2380 .deviceId(stylusDeviceId2)
2381 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2382 .build());
2383 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2384 .deviceId(stylusDeviceId2)
2385 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2386 .build());
2387
2388 // First stylus is canceled, second one takes over.
2389 window->consumeMotionEvent(
2390 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2391 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2392 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2393
2394 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2395 .deviceId(stylusDeviceId1)
2396 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2397 .build());
2398 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002399 window->assertNoEvents();
2400}
2401
2402/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002403 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2404 * both stylus devices can function simultaneously.
2405 */
2406TEST_F(InputDispatcherMultiDeviceTest, TwoStylusDevicesActiveAtTheSameTime) {
2407 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2408 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002409 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2410 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002411 window->setFrame(Rect(0, 0, 200, 200));
2412
2413 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2414
2415 constexpr int32_t stylusDeviceId1 = 3;
2416 constexpr int32_t stylusDeviceId2 = 5;
2417
2418 // Touch down on window
2419 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2420 .deviceId(stylusDeviceId1)
2421 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2422 .build());
2423 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2424 .deviceId(stylusDeviceId1)
2425 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2426 .build());
2427 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2428 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2429
2430 // Second stylus down
2431 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2432 .deviceId(stylusDeviceId2)
2433 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2434 .build());
2435 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2436 .deviceId(stylusDeviceId2)
2437 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2438 .build());
2439 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2440 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2441
2442 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2443 .deviceId(stylusDeviceId1)
2444 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2445 .build());
2446 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2447 window->assertNoEvents();
2448}
2449
2450/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002451 * One window. Touch down on the window. Then, stylus down on the window from another device.
2452 * Ensure that is canceled, because stylus down should be preferred over touch.
2453 */
2454TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002455 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002456 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002457 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2458 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002459 window->setFrame(Rect(0, 0, 200, 200));
2460
2461 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2462
2463 constexpr int32_t touchDeviceId = 4;
2464 constexpr int32_t stylusDeviceId = 2;
2465
2466 // Touch down on window
2467 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2468 .deviceId(touchDeviceId)
2469 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2470 .build());
2471 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2472 .deviceId(touchDeviceId)
2473 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2474 .build());
2475 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2476 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2477
2478 // Stylus down on the window
2479 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2480 .deviceId(stylusDeviceId)
2481 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2482 .build());
2483 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2484 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2485
2486 // Subsequent stylus movements are delivered correctly
2487 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2488 .deviceId(stylusDeviceId)
2489 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2490 .build());
2491 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2492 WithCoords(101, 111)));
2493}
2494
2495/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002496 * One window. Touch down on the window. Then, stylus down on the window from another device.
2497 * Ensure that both touch and stylus are functioning independently.
2498 */
2499TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusDown) {
2500 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2501 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002502 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2503 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002504 window->setFrame(Rect(0, 0, 200, 200));
2505
2506 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2507
2508 constexpr int32_t touchDeviceId = 4;
2509 constexpr int32_t stylusDeviceId = 2;
2510
2511 // Touch down on window
2512 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2513 .deviceId(touchDeviceId)
2514 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2515 .build());
2516 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2517 .deviceId(touchDeviceId)
2518 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2519 .build());
2520 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2521 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2522
2523 // Stylus down on the window
2524 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2525 .deviceId(stylusDeviceId)
2526 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2527 .build());
2528 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2529
2530 // Subsequent stylus movements are delivered correctly
2531 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2532 .deviceId(stylusDeviceId)
2533 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2534 .build());
2535 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2536 WithCoords(101, 111)));
2537
2538 // Touch continues to work too
2539 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2540 .deviceId(touchDeviceId)
2541 .pointer(PointerBuilder(0, ToolType::FINGER).x(148).y(149))
2542 .build());
2543 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2544}
2545
2546/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002547 * Two windows: a window on the left and a window on the right.
2548 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2549 * down. Then, on the left window, also place second touch pointer down.
2550 * This test tries to reproduce a crash.
2551 * In the buggy implementation, second pointer down on the left window would cause a crash.
2552 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002553TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch_legacy) {
2554 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002555 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002556 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2557 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002558 leftWindow->setFrame(Rect(0, 0, 200, 200));
2559
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002560 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2561 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002562 rightWindow->setFrame(Rect(200, 0, 400, 200));
2563
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002564 mDispatcher->onWindowInfosChanged(
2565 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002566
2567 const int32_t touchDeviceId = 4;
2568 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002569
2570 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002571 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2572 .deviceId(mouseDeviceId)
2573 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2574 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002575 leftWindow->consumeMotionEvent(
2576 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2577
2578 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002579 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2580 .deviceId(mouseDeviceId)
2581 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2582 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2583 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002584
2585 leftWindow->consumeMotionEvent(
2586 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2587 leftWindow->consumeMotionEvent(
2588 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2589
Prabir Pradhan678438e2023-04-13 19:32:51 +00002590 mDispatcher->notifyMotion(
2591 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2592 .deviceId(mouseDeviceId)
2593 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2594 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2595 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2596 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002597 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2598
2599 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002600 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2601 .deviceId(touchDeviceId)
2602 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2603 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002604 leftWindow->assertNoEvents();
2605
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002606 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2607
2608 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002609 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2610 .deviceId(touchDeviceId)
2611 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2612 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2613 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002614 // Since this is now a new splittable pointer going down on the left window, and it's coming
2615 // from a different device, the current gesture in the left window (pointer down) should first
2616 // be canceled.
2617 leftWindow->consumeMotionEvent(
2618 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002619 leftWindow->consumeMotionEvent(
2620 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2621 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2622 // current implementation.
2623 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2624 rightWindow->consumeMotionEvent(
2625 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2626
2627 leftWindow->assertNoEvents();
2628 rightWindow->assertNoEvents();
2629}
2630
2631/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002632 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002633 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2634 * down. Then, on the left window, also place second touch pointer down.
2635 * This test tries to reproduce a crash.
2636 * In the buggy implementation, second pointer down on the left window would cause a crash.
2637 */
2638TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
2639 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2640 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002641 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2642 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002643 leftWindow->setFrame(Rect(0, 0, 200, 200));
2644
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002645 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2646 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002647 rightWindow->setFrame(Rect(200, 0, 400, 200));
2648
2649 mDispatcher->onWindowInfosChanged(
2650 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2651
2652 const int32_t touchDeviceId = 4;
2653 const int32_t mouseDeviceId = 6;
2654
2655 // Start hovering over the left window
2656 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2657 .deviceId(mouseDeviceId)
2658 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2659 .build());
2660 leftWindow->consumeMotionEvent(
2661 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2662
2663 // Mouse down on left window
2664 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2665 .deviceId(mouseDeviceId)
2666 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2667 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2668 .build());
2669
2670 leftWindow->consumeMotionEvent(
2671 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2672 leftWindow->consumeMotionEvent(
2673 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2674
2675 mDispatcher->notifyMotion(
2676 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2677 .deviceId(mouseDeviceId)
2678 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2679 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2680 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2681 .build());
2682 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2683
2684 // First touch pointer down on right window
2685 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2686 .deviceId(touchDeviceId)
2687 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2688 .build());
2689 leftWindow->assertNoEvents();
2690
2691 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2692
2693 // Second touch pointer down on left window
2694 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2695 .deviceId(touchDeviceId)
2696 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2697 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2698 .build());
2699 // Since this is now a new splittable pointer going down on the left window, and it's coming
2700 // from a different device, it will be split and delivered to left window separately.
2701 leftWindow->consumeMotionEvent(
2702 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2703 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2704 // current implementation.
2705 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2706 rightWindow->consumeMotionEvent(
2707 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2708
2709 leftWindow->assertNoEvents();
2710 rightWindow->assertNoEvents();
2711}
2712
2713/**
2714 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002715 * Mouse is hovered on the left window and stylus is hovered on the right window.
2716 */
2717TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2718 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002719 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2720 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002721 leftWindow->setFrame(Rect(0, 0, 200, 200));
2722
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002723 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2724 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002725 rightWindow->setFrame(Rect(200, 0, 400, 200));
2726
2727 mDispatcher->onWindowInfosChanged(
2728 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2729
2730 const int32_t stylusDeviceId = 3;
2731 const int32_t mouseDeviceId = 6;
2732
2733 // Start hovering over the left window
2734 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2735 .deviceId(mouseDeviceId)
2736 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2737 .build());
2738 leftWindow->consumeMotionEvent(
2739 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2740
2741 // Stylus hovered on right window
2742 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2743 .deviceId(stylusDeviceId)
2744 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2745 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002746 rightWindow->consumeMotionEvent(
2747 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2748
2749 // Subsequent HOVER_MOVE events are dispatched correctly.
2750 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2751 .deviceId(mouseDeviceId)
2752 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2753 .build());
2754 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002755 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002756
2757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2758 .deviceId(stylusDeviceId)
2759 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2760 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002761 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002762 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002763
2764 leftWindow->assertNoEvents();
2765 rightWindow->assertNoEvents();
2766}
2767
2768/**
2769 * Three windows: a window on the left and a window on the right.
2770 * And a spy window that's positioned above all of them.
2771 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2772 * Check the stream that's received by the spy.
2773 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002774TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy_legacy) {
2775 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002776 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2777
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002778 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2779 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002780 spyWindow->setFrame(Rect(0, 0, 400, 400));
2781 spyWindow->setTrustedOverlay(true);
2782 spyWindow->setSpy(true);
2783
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002784 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2785 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002786 leftWindow->setFrame(Rect(0, 0, 200, 200));
2787
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002788 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2789 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002790
2791 rightWindow->setFrame(Rect(200, 0, 400, 200));
2792
2793 mDispatcher->onWindowInfosChanged(
2794 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2795
2796 const int32_t stylusDeviceId = 1;
2797 const int32_t touchDeviceId = 2;
2798
2799 // Stylus down on the left window
2800 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2801 .deviceId(stylusDeviceId)
2802 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2803 .build());
2804 leftWindow->consumeMotionEvent(
2805 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2806 spyWindow->consumeMotionEvent(
2807 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2808
2809 // Touch down on the right window
2810 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2811 .deviceId(touchDeviceId)
2812 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2813 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002814 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002815 rightWindow->consumeMotionEvent(
2816 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002817
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002818 // Spy window does not receive touch events, because stylus events take precedence, and it
2819 // already has an active stylus gesture.
2820
2821 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002822 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2823 .deviceId(stylusDeviceId)
2824 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2825 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002826 leftWindow->consumeMotionEvent(
2827 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2828 spyWindow->consumeMotionEvent(
2829 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002830
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002831 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002832 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2833 .deviceId(touchDeviceId)
2834 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2835 .build());
2836 rightWindow->consumeMotionEvent(
2837 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002838
2839 spyWindow->assertNoEvents();
2840 leftWindow->assertNoEvents();
2841 rightWindow->assertNoEvents();
2842}
2843
2844/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002845 * Three windows: a window on the left and a window on the right.
2846 * And a spy window that's positioned above all of them.
2847 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2848 * Check the stream that's received by the spy.
2849 */
2850TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2851 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2852 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2853
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002854 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2855 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002856 spyWindow->setFrame(Rect(0, 0, 400, 400));
2857 spyWindow->setTrustedOverlay(true);
2858 spyWindow->setSpy(true);
2859
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002860 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2861 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002862 leftWindow->setFrame(Rect(0, 0, 200, 200));
2863
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002864 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2865 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002866
2867 rightWindow->setFrame(Rect(200, 0, 400, 200));
2868
2869 mDispatcher->onWindowInfosChanged(
2870 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2871
2872 const int32_t stylusDeviceId = 1;
2873 const int32_t touchDeviceId = 2;
2874
2875 // Stylus down on the left window
2876 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2877 .deviceId(stylusDeviceId)
2878 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2879 .build());
2880 leftWindow->consumeMotionEvent(
2881 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2882 spyWindow->consumeMotionEvent(
2883 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2884
2885 // Touch down on the right window
2886 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2887 .deviceId(touchDeviceId)
2888 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2889 .build());
2890 leftWindow->assertNoEvents();
2891 rightWindow->consumeMotionEvent(
2892 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2893 spyWindow->consumeMotionEvent(
2894 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2895
2896 // Stylus movements continue. They should be delivered to the left window and to the spy window
2897 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2898 .deviceId(stylusDeviceId)
2899 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2900 .build());
2901 leftWindow->consumeMotionEvent(
2902 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2903 spyWindow->consumeMotionEvent(
2904 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2905
2906 // Further touch MOVE events keep going to the right window and to the spy
2907 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2908 .deviceId(touchDeviceId)
2909 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2910 .build());
2911 rightWindow->consumeMotionEvent(
2912 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2913 spyWindow->consumeMotionEvent(
2914 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2915
2916 spyWindow->assertNoEvents();
2917 leftWindow->assertNoEvents();
2918 rightWindow->assertNoEvents();
2919}
2920
2921/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002922 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2923 * both.
2924 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002925 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002926 * At the same time, left and right should be getting independent streams of hovering and touch,
2927 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002928 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002929TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002930 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002931 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2932
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002933 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2934 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002935 spyWindow->setFrame(Rect(0, 0, 400, 400));
2936 spyWindow->setTrustedOverlay(true);
2937 spyWindow->setSpy(true);
2938
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002939 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2940 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002941 leftWindow->setFrame(Rect(0, 0, 200, 200));
2942
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002943 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2944 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002945 rightWindow->setFrame(Rect(200, 0, 400, 200));
2946
2947 mDispatcher->onWindowInfosChanged(
2948 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2949
2950 const int32_t stylusDeviceId = 1;
2951 const int32_t touchDeviceId = 2;
2952
2953 // Stylus hover on the left window
2954 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2955 .deviceId(stylusDeviceId)
2956 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2957 .build());
2958 leftWindow->consumeMotionEvent(
2959 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2960 spyWindow->consumeMotionEvent(
2961 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2962
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002963 // Touch down on the right window. Spy doesn't receive this touch because it already has
2964 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002965 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2966 .deviceId(touchDeviceId)
2967 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2968 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002969 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002970 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002971 rightWindow->consumeMotionEvent(
2972 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2973
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002974 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002975 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2976 .deviceId(stylusDeviceId)
2977 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2978 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002979 leftWindow->consumeMotionEvent(
2980 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002981 spyWindow->consumeMotionEvent(
2982 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002983
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002984 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002985 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2986 .deviceId(touchDeviceId)
2987 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2988 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002989 rightWindow->consumeMotionEvent(
2990 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2991
2992 spyWindow->assertNoEvents();
2993 leftWindow->assertNoEvents();
2994 rightWindow->assertNoEvents();
2995}
2996
2997/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002998 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2999 * both.
3000 * Check hover in left window and touch down in the right window.
3001 * At first, spy should receive hover. Next, spy should receive touch.
3002 * At the same time, left and right should be getting independent streams of hovering and touch,
3003 * respectively.
3004 */
3005TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverDoesNotBlockTouchWithSpy) {
3006 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3007 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3008
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003009 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3010 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003011 spyWindow->setFrame(Rect(0, 0, 400, 400));
3012 spyWindow->setTrustedOverlay(true);
3013 spyWindow->setSpy(true);
3014
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003015 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3016 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003017 leftWindow->setFrame(Rect(0, 0, 200, 200));
3018
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003019 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3020 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003021 rightWindow->setFrame(Rect(200, 0, 400, 200));
3022
3023 mDispatcher->onWindowInfosChanged(
3024 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3025
3026 const int32_t stylusDeviceId = 1;
3027 const int32_t touchDeviceId = 2;
3028
3029 // Stylus hover on the left window
3030 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3031 .deviceId(stylusDeviceId)
3032 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3033 .build());
3034 leftWindow->consumeMotionEvent(
3035 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3036 spyWindow->consumeMotionEvent(
3037 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3038
3039 // Touch down on the right window.
3040 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3041 .deviceId(touchDeviceId)
3042 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3043 .build());
3044 leftWindow->assertNoEvents();
3045 spyWindow->consumeMotionEvent(
3046 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3047 rightWindow->consumeMotionEvent(
3048 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3049
3050 // Stylus movements continue. They should be delivered to the left window and the spy.
3051 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3052 .deviceId(stylusDeviceId)
3053 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3054 .build());
3055 leftWindow->consumeMotionEvent(
3056 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3057 spyWindow->consumeMotionEvent(
3058 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3059
3060 // Touch movements continue. They should be delivered to the right window and the spy
3061 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3062 .deviceId(touchDeviceId)
3063 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3064 .build());
3065 rightWindow->consumeMotionEvent(
3066 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3067 spyWindow->consumeMotionEvent(
3068 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3069
3070 spyWindow->assertNoEvents();
3071 leftWindow->assertNoEvents();
3072 rightWindow->assertNoEvents();
3073}
3074
3075/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003076 * On a single window, use two different devices: mouse and touch.
3077 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3078 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3079 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3080 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3081 * represent a new gesture.
3082 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003083TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown_legacy) {
3084 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003085 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003086 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3087 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003088 window->setFrame(Rect(0, 0, 400, 400));
3089
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003090 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003091
3092 const int32_t touchDeviceId = 4;
3093 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003094
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003095 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003096 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3097 .deviceId(touchDeviceId)
3098 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3099 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003100 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003101 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3102 .deviceId(touchDeviceId)
3103 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3104 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3105 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003106 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003107 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3108 .deviceId(touchDeviceId)
3109 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3110 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3111 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003112 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3113 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3114 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3115
3116 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003117 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3118 .deviceId(mouseDeviceId)
3119 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3120 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3121 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003122
3123 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003124 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003125 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3126
Prabir Pradhan678438e2023-04-13 19:32:51 +00003127 mDispatcher->notifyMotion(
3128 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3129 .deviceId(mouseDeviceId)
3130 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3131 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3132 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3133 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003134 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3135
3136 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003137 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3138 .deviceId(touchDeviceId)
3139 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3140 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3141 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003142 // Since we already canceled this touch gesture, it will be ignored until a completely new
3143 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3144 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3145 // However, mouse movements should continue to work.
3146 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3147 .deviceId(mouseDeviceId)
3148 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3149 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3150 .build());
3151 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3152
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003153 window->assertNoEvents();
3154}
3155
3156/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003157 * On a single window, use two different devices: mouse and touch.
3158 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3159 * Mouse is clicked next, which should not interfere with the touch stream.
3160 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is also
3161 * delivered correctly.
3162 */
3163TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
3164 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3165 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003166 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3167 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003168 window->setFrame(Rect(0, 0, 400, 400));
3169
3170 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3171
3172 const int32_t touchDeviceId = 4;
3173 const int32_t mouseDeviceId = 6;
3174
3175 // First touch pointer down
3176 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3177 .deviceId(touchDeviceId)
3178 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3179 .build());
3180 // Second touch pointer down
3181 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3182 .deviceId(touchDeviceId)
3183 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3184 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3185 .build());
3186 // First touch pointer lifts. The second one remains down
3187 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3188 .deviceId(touchDeviceId)
3189 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3190 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3191 .build());
3192 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3193 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3194 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3195
3196 // Mouse down
3197 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3198 .deviceId(mouseDeviceId)
3199 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3200 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3201 .build());
3202
3203 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3204
3205 mDispatcher->notifyMotion(
3206 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3207 .deviceId(mouseDeviceId)
3208 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3209 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3210 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3211 .build());
3212 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3213
3214 // Second touch pointer down.
3215 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3216 .deviceId(touchDeviceId)
3217 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3218 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3219 .build());
3220 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_0_DOWN), WithDeviceId(touchDeviceId),
3221 WithPointerCount(2u)));
3222
3223 // Mouse movements should continue to work
3224 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3225 .deviceId(mouseDeviceId)
3226 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3227 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3228 .build());
3229 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3230
3231 window->assertNoEvents();
3232}
3233
3234/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003235 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3236 * the injected event.
3237 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003238TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent_legacy) {
3239 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003240 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003241 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3242 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003243 window->setFrame(Rect(0, 0, 400, 400));
3244
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003245 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003246
3247 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003248 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3249 // completion.
3250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003251 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003252 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3253 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003254 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003255 .build()));
3256 window->consumeMotionEvent(
3257 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3258
3259 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3260 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003261 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3262 .deviceId(touchDeviceId)
3263 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3264 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003265
3266 window->consumeMotionEvent(
3267 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3268 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3269}
3270
3271/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003272 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event runs
3273 * parallel to the injected event.
3274 */
3275TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
3276 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3277 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003278 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3279 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003280 window->setFrame(Rect(0, 0, 400, 400));
3281
3282 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3283
3284 const int32_t touchDeviceId = 4;
3285 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3286 // completion.
3287 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3288 injectMotionEvent(*mDispatcher,
3289 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3290 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
3291 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3292 .build()));
3293 window->consumeMotionEvent(
3294 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3295
3296 // Now a real touch comes. The injected pointer will remain, and the new gesture will also be
3297 // allowed through.
3298 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3299 .deviceId(touchDeviceId)
3300 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3301 .build());
3302 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3303}
3304
3305/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003306 * This test is similar to the test above, but the sequence of injected events is different.
3307 *
3308 * Two windows: a window on the left and a window on the right.
3309 * Mouse is hovered over the left window.
3310 * Next, we tap on the left window, where the cursor was last seen.
3311 *
3312 * After that, we inject one finger down onto the right window, and then a second finger down onto
3313 * the left window.
3314 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3315 * window (first), and then another on the left window (second).
3316 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3317 * In the buggy implementation, second finger down on the left window would cause a crash.
3318 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003319TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch_legacy) {
3320 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003321 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003322 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3323 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003324 leftWindow->setFrame(Rect(0, 0, 200, 200));
3325
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003326 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3327 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003328 rightWindow->setFrame(Rect(200, 0, 400, 200));
3329
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003330 mDispatcher->onWindowInfosChanged(
3331 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003332
3333 const int32_t mouseDeviceId = 6;
3334 const int32_t touchDeviceId = 4;
3335 // Hover over the left window. Keep the cursor there.
3336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003337 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003338 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3339 AINPUT_SOURCE_MOUSE)
3340 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003341 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003342 .build()));
3343 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3344
3345 // Tap on left window
3346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003347 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003348 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3349 AINPUT_SOURCE_TOUCHSCREEN)
3350 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003351 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003352 .build()));
3353
3354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003355 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003356 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3357 AINPUT_SOURCE_TOUCHSCREEN)
3358 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003359 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003360 .build()));
3361 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3362 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3363 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3364
3365 // First finger down on right window
3366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003367 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003368 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3369 AINPUT_SOURCE_TOUCHSCREEN)
3370 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003371 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003372 .build()));
3373 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3374
3375 // Second finger down on the left window
3376 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003377 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003378 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3379 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003380 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3381 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003382 .build()));
3383 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3384 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3385
3386 // No more events
3387 leftWindow->assertNoEvents();
3388 rightWindow->assertNoEvents();
3389}
3390
3391/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003392 * This test is similar to the test above, but the sequence of injected events is different.
3393 *
3394 * Two windows: a window on the left and a window on the right.
3395 * Mouse is hovered over the left window.
3396 * Next, we tap on the left window, where the cursor was last seen.
3397 *
3398 * After that, we send one finger down onto the right window, and then a second finger down onto
3399 * the left window.
3400 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3401 * window (first), and then another on the left window (second).
3402 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3403 * In the buggy implementation, second finger down on the left window would cause a crash.
3404 */
3405TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
3406 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3407 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003408 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3409 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003410 leftWindow->setFrame(Rect(0, 0, 200, 200));
3411
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003412 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3413 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003414 rightWindow->setFrame(Rect(200, 0, 400, 200));
3415
3416 mDispatcher->onWindowInfosChanged(
3417 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3418
3419 const int32_t mouseDeviceId = 6;
3420 const int32_t touchDeviceId = 4;
3421 // Hover over the left window. Keep the cursor there.
3422 mDispatcher->notifyMotion(
3423 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3424 .deviceId(mouseDeviceId)
3425 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3426 .build());
3427 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3428
3429 // Tap on left window
3430 mDispatcher->notifyMotion(
3431 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3432 .deviceId(touchDeviceId)
3433 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3434 .build());
3435
3436 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3437 .deviceId(touchDeviceId)
3438 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3439 .build());
3440 leftWindow->consumeMotionEvent(
3441 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithDeviceId(touchDeviceId)));
3442 leftWindow->consumeMotionEvent(
3443 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithDeviceId(touchDeviceId)));
3444
3445 // First finger down on right window
3446 mDispatcher->notifyMotion(
3447 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3448 .deviceId(touchDeviceId)
3449 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3450 .build());
3451 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3452
3453 // Second finger down on the left window
3454 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3455 .deviceId(touchDeviceId)
3456 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3457 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
3458 .build());
3459 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3460 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3461
3462 // No more events
3463 leftWindow->assertNoEvents();
3464 rightWindow->assertNoEvents();
3465}
3466
3467/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003468 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3469 * While the touch is down, new hover events from the stylus device should be ignored. After the
3470 * touch is gone, stylus hovering should start working again.
3471 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003472TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003473 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003474 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003475 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3476 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003477 window->setFrame(Rect(0, 0, 200, 200));
3478
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003479 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003480
3481 const int32_t stylusDeviceId = 5;
3482 const int32_t touchDeviceId = 4;
3483 // Start hovering with stylus
3484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003485 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003486 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003487 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003488 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003489 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003490 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003491
3492 // Finger down on the window
3493 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003494 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003495 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003496 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003497 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003498 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003499 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003500
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003501 // Continue hovering with stylus.
3502 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003503 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003504 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3505 AINPUT_SOURCE_STYLUS)
3506 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003507 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003508 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003509 // Hovers continue to work
3510 window->consumeMotionEvent(
3511 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003512
3513 // Lift up the finger
3514 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003515 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003516 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3517 AINPUT_SOURCE_TOUCHSCREEN)
3518 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003519 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003520 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003521
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003523 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003524 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3525 AINPUT_SOURCE_STYLUS)
3526 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003527 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003528 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003529 window->consumeMotionEvent(
3530 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003531 window->assertNoEvents();
3532}
3533
3534/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003535 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3536 * While the touch is down, hovering from the stylus is not affected. After the touch is gone,
3537 * check that the stylus hovering continues to work.
3538 */
3539TEST_F(InputDispatcherMultiDeviceTest, StylusHoverWithTouchTap) {
3540 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3541 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003542 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3543 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003544 window->setFrame(Rect(0, 0, 200, 200));
3545
3546 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3547
3548 const int32_t stylusDeviceId = 5;
3549 const int32_t touchDeviceId = 4;
3550 // Start hovering with stylus
3551 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3552 .deviceId(stylusDeviceId)
3553 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3554 .build());
3555 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3556
3557 // Finger down on the window
3558 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3559 .deviceId(touchDeviceId)
3560 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3561 .build());
3562 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3563
3564 // Continue hovering with stylus.
3565 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3566 .deviceId(stylusDeviceId)
3567 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
3568 .build());
3569 // Hovers continue to work
3570 window->consumeMotionEvent(
3571 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3572
3573 // Lift up the finger
3574 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3575 .deviceId(touchDeviceId)
3576 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3577 .build());
3578 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
3579
3580 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3581 .deviceId(stylusDeviceId)
3582 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
3583 .build());
3584 window->consumeMotionEvent(
3585 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3586 window->assertNoEvents();
3587}
3588
3589/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003590 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3591 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3592 *
3593 * Two windows: one on the left and one on the right.
3594 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3595 * Stylus down on the left window, and then touch down on the right window.
3596 * Check that the right window doesn't get touches while the stylus is down on the left window.
3597 */
3598TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3599 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3600 sp<FakeWindowHandle> leftWindow =
3601 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003602 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003603 leftWindow->setFrame(Rect(0, 0, 100, 100));
3604
3605 sp<FakeWindowHandle> sbtRightWindow =
3606 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003607 "Stylus blocks touch (right) window",
3608 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003609 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3610 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3611
3612 mDispatcher->onWindowInfosChanged(
3613 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3614
3615 const int32_t stylusDeviceId = 5;
3616 const int32_t touchDeviceId = 4;
3617
3618 // Stylus down in the left window
3619 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3620 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3621 .deviceId(stylusDeviceId)
3622 .build());
3623 leftWindow->consumeMotionEvent(
3624 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3625
3626 // Finger tap on the right window
3627 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3628 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3629 .deviceId(touchDeviceId)
3630 .build());
3631 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3632 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3633 .deviceId(touchDeviceId)
3634 .build());
3635
3636 // The touch should be blocked, because stylus is down somewhere else on screen!
3637 sbtRightWindow->assertNoEvents();
3638
3639 // Continue stylus motion, and ensure it's not impacted.
3640 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3641 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3642 .deviceId(stylusDeviceId)
3643 .build());
3644 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3645 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3646 .deviceId(stylusDeviceId)
3647 .build());
3648 leftWindow->consumeMotionEvent(
3649 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3650 leftWindow->consumeMotionEvent(
3651 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3652
3653 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3654 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3655 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3656 .deviceId(touchDeviceId)
3657 .build());
3658 sbtRightWindow->consumeMotionEvent(
3659 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3660}
3661
3662/**
3663 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3664 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3665 *
3666 * Two windows: one on the left and one on the right.
3667 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3668 * Stylus hover on the left window, and then touch down on the right window.
3669 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3670 */
3671TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3672 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3673 sp<FakeWindowHandle> leftWindow =
3674 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003675 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003676 leftWindow->setFrame(Rect(0, 0, 100, 100));
3677
3678 sp<FakeWindowHandle> sbtRightWindow =
3679 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003680 "Stylus blocks touch (right) window",
3681 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003682 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3683 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3684
3685 mDispatcher->onWindowInfosChanged(
3686 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3687
3688 const int32_t stylusDeviceId = 5;
3689 const int32_t touchDeviceId = 4;
3690
3691 // Stylus hover in the left window
3692 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3693 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3694 .deviceId(stylusDeviceId)
3695 .build());
3696 leftWindow->consumeMotionEvent(
3697 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3698
3699 // Finger tap on the right window
3700 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3701 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3702 .deviceId(touchDeviceId)
3703 .build());
3704 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3705 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3706 .deviceId(touchDeviceId)
3707 .build());
3708
3709 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3710 sbtRightWindow->assertNoEvents();
3711
3712 // Continue stylus motion, and ensure it's not impacted.
3713 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3714 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3715 .deviceId(stylusDeviceId)
3716 .build());
3717 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3718 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3719 .deviceId(stylusDeviceId)
3720 .build());
3721 leftWindow->consumeMotionEvent(
3722 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3723 leftWindow->consumeMotionEvent(
3724 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3725
3726 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3727 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3728 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3729 .deviceId(touchDeviceId)
3730 .build());
3731 sbtRightWindow->consumeMotionEvent(
3732 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3733}
3734
3735/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003736 * A spy window above a window with no input channel.
3737 * Start hovering with a stylus device, and then tap with it.
3738 * Ensure spy window receives the entire sequence.
3739 */
3740TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003742 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3743 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003744 spyWindow->setFrame(Rect(0, 0, 200, 200));
3745 spyWindow->setTrustedOverlay(true);
3746 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003747 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3748 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003749 window->setNoInputChannel(true);
3750 window->setFrame(Rect(0, 0, 200, 200));
3751
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003752 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003753
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003754 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003755 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3756 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3757 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003758 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3759 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003760 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3761 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3762 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003763 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3764
3765 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003766 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3767 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3768 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003769 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3770
3771 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003772 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3773 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3774 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003775 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3776
3777 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003778 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3779 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3780 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003781 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3782 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003783 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3784 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3785 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003786 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3787
3788 // No more events
3789 spyWindow->assertNoEvents();
3790 window->assertNoEvents();
3791}
3792
3793/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003794 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3795 * rejected. But since we already have an ongoing gesture, this event should be processed.
3796 * This prevents inconsistent events being handled inside the dispatcher.
3797 */
3798TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3799 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3800
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003801 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3802 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003803 window->setFrame(Rect(0, 0, 200, 200));
3804
3805 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3806
3807 // Start hovering with stylus
3808 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3809 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3810 .build());
3811 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3812
3813 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3814 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3815 .build();
3816 // Make this 'hoverExit' event stale
3817 mFakePolicy->setStaleEventTimeout(100ms);
3818 std::this_thread::sleep_for(100ms);
3819
3820 // It shouldn't be dropped by the dispatcher, even though it's stale.
3821 mDispatcher->notifyMotion(hoverExit);
3822 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3823
3824 // Stylus starts hovering again! There should be no crash.
3825 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3826 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3827 .build());
3828 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3829}
3830
3831/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003832 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3833 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3834 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3835 * While the mouse is down, new move events from the touch device should be ignored.
3836 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003837TEST_F(InputDispatcherTest, TouchPilferAndMouseMove_legacy) {
3838 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003839 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003840 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3841 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003842 spyWindow->setFrame(Rect(0, 0, 200, 200));
3843 spyWindow->setTrustedOverlay(true);
3844 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003845 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3846 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003847 window->setFrame(Rect(0, 0, 200, 200));
3848
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003849 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003850
3851 const int32_t mouseDeviceId = 7;
3852 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003853
3854 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003855 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3856 .deviceId(mouseDeviceId)
3857 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3858 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003859 spyWindow->consumeMotionEvent(
3860 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3861 window->consumeMotionEvent(
3862 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3863
3864 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003865 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3866 .deviceId(touchDeviceId)
3867 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3868 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003869 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3870 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3871 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3872 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3873
Prabir Pradhan678438e2023-04-13 19:32:51 +00003874 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3875 .deviceId(touchDeviceId)
3876 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3877 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003878 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3879 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3880
3881 // Pilfer the stream
3882 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3883 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3884
Prabir Pradhan678438e2023-04-13 19:32:51 +00003885 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3886 .deviceId(touchDeviceId)
3887 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3888 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003889 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3890
3891 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003892 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3893 .deviceId(mouseDeviceId)
3894 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3895 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3896 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003897
3898 spyWindow->consumeMotionEvent(
3899 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3900 spyWindow->consumeMotionEvent(
3901 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3902 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3903
Prabir Pradhan678438e2023-04-13 19:32:51 +00003904 mDispatcher->notifyMotion(
3905 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3906 .deviceId(mouseDeviceId)
3907 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3908 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3909 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3910 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003911 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3912 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3913
3914 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3916 .deviceId(mouseDeviceId)
3917 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3918 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3919 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003920 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3921 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3922
3923 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003924 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3925 .deviceId(touchDeviceId)
3926 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3927 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003928
3929 // No more events
3930 spyWindow->assertNoEvents();
3931 window->assertNoEvents();
3932}
3933
3934/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003935 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3936 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3937 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3938 * While the mouse is down, new move events from the touch device should continue to work.
3939 */
3940TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3941 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3942 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003943 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3944 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003945 spyWindow->setFrame(Rect(0, 0, 200, 200));
3946 spyWindow->setTrustedOverlay(true);
3947 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003948 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3949 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003950 window->setFrame(Rect(0, 0, 200, 200));
3951
3952 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
3953
3954 const int32_t mouseDeviceId = 7;
3955 const int32_t touchDeviceId = 4;
3956
3957 // Hover a bit with mouse first
3958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3959 .deviceId(mouseDeviceId)
3960 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3961 .build());
3962 spyWindow->consumeMotionEvent(
3963 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3964 window->consumeMotionEvent(
3965 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3966
3967 // Start touching
3968 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3969 .deviceId(touchDeviceId)
3970 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3971 .build());
3972
3973 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3974 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3975
3976 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3977 .deviceId(touchDeviceId)
3978 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3979 .build());
3980 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3981 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3982
3983 // Pilfer the stream
3984 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3985 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3986 // Hover is not pilfered! Only touch.
3987
3988 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3989 .deviceId(touchDeviceId)
3990 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3991 .build());
3992 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3993
3994 // Mouse down
3995 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3996 .deviceId(mouseDeviceId)
3997 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3998 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3999 .build());
4000
4001 spyWindow->consumeMotionEvent(
4002 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4003 spyWindow->consumeMotionEvent(
4004 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4005 window->consumeMotionEvent(
4006 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4007 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4008
4009 mDispatcher->notifyMotion(
4010 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4011 .deviceId(mouseDeviceId)
4012 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4013 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4014 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4015 .build());
4016 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4017 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4018
4019 // Mouse move!
4020 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4021 .deviceId(mouseDeviceId)
4022 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4023 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4024 .build());
4025 spyWindow->consumeMotionEvent(
4026 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4027 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4028
4029 // Touch move!
4030 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4031 .deviceId(touchDeviceId)
4032 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4033 .build());
4034 spyWindow->consumeMotionEvent(
4035 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4036
4037 // No more events
4038 spyWindow->assertNoEvents();
4039 window->assertNoEvents();
4040}
4041
4042/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004043 * On the display, have a single window, and also an area where there's no window.
4044 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
4045 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
4046 */
4047TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
4048 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4049 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004050 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004051
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004052 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004053
4054 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00004055 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004056
4057 mDispatcher->waitForIdle();
4058 window->assertNoEvents();
4059
4060 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004061 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004062 mDispatcher->waitForIdle();
4063 window->consumeMotionDown();
4064}
4065
4066/**
4067 * Same test as above, but instead of touching the empty space, the first touch goes to
4068 * non-touchable window.
4069 */
4070TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
4071 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4072 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004073 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004074 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4075 window1->setTouchable(false);
4076 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004077 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004078 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4079
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004080 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004081
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004082 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004083 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004084
4085 mDispatcher->waitForIdle();
4086 window1->assertNoEvents();
4087 window2->assertNoEvents();
4088
4089 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004090 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004091 mDispatcher->waitForIdle();
4092 window2->consumeMotionDown();
4093}
4094
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004095/**
4096 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
4097 * to the event time of the first ACTION_DOWN sent to the particular window.
4098 */
4099TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
4100 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4101 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004102 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004103 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4104 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004105 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004106 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4107
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004108 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004109
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004110 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004111 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004112 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004113
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004114 const std::unique_ptr<MotionEvent> firstDown =
4115 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4116 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004117 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004118
4119 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004120 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004121 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004122
4123 const std::unique_ptr<MotionEvent> secondDown =
4124 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4125 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
4126 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
4127 // We currently send MOVE events to all windows receiving a split touch when there is any change
4128 // in the touch state, even when none of the pointers in the split window actually moved.
4129 // Document this behavior in the test.
4130 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004131
4132 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004133 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004134 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004135
4136 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4137 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004138
4139 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004140 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004141 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004142
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004143 window2->consumeMotionEvent(
4144 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
4145 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004146
4147 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004148 mDispatcher->notifyMotion(
4149 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004150 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004151
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004152 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
4153 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4154
4155 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004156 mDispatcher->notifyMotion(
4157 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004158 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004159
4160 window1->consumeMotionEvent(
4161 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
4162 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004163}
4164
Siarhei Vishniakouac42d242024-06-28 10:43:53 -07004165/**
4166 * When events are not split, the downTime should be adjusted such that the downTime corresponds
4167 * to the event time of the first ACTION_DOWN. If a new window appears, it should not affect
4168 * the event routing because the first window prevents splitting.
4169 */
4170TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTimeForNewWindow) {
4171 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4172 sp<FakeWindowHandle> window1 =
4173 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4174 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4175 window1->setPreventSplitting(true);
4176
4177 sp<FakeWindowHandle> window2 =
4178 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4179 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4180
4181 mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4182
4183 // Touch down on the first window
4184 NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4185 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4186 .build();
4187 mDispatcher->notifyMotion(downArgs);
4188
4189 window1->consumeMotionEvent(
4190 AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4191
4192 // Second window is added
4193 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4194
4195 // Now touch down on the window with another pointer
4196 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4197 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4198 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4199 .downTime(downArgs.downTime)
4200 .build());
4201 window1->consumeMotionPointerDown(1, AllOf(WithDownTime(downArgs.downTime)));
4202
4203 // Finish the gesture
4204 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4205 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4206 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4207 .downTime(downArgs.downTime)
4208 .build());
4209 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4210 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4211 .downTime(downArgs.downTime)
4212 .build());
4213 window1->consumeMotionPointerUp(1, AllOf(WithDownTime(downArgs.downTime)));
4214 window1->consumeMotionEvent(
4215 AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4216 window2->assertNoEvents();
4217}
4218
4219/**
4220 * When splitting touch events, the downTime should be adjusted such that the downTime corresponds
4221 * to the event time of the first ACTION_DOWN sent to the new window.
4222 * If a new window that does not support split appears on the screen and gets touched with the
4223 * second finger, it should not get any events because it doesn't want split touches. At the same
4224 * time, the first window should not get the pointer_down event because it supports split touches
4225 * (and the touch occurred outside of the bounds of window1).
4226 */
4227TEST_F(InputDispatcherTest, SplitTouchesDropsEventForNonSplittableSecondWindow) {
4228 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4229 sp<FakeWindowHandle> window1 =
4230 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4231 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4232
4233 sp<FakeWindowHandle> window2 =
4234 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4235 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4236
4237 mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4238
4239 // Touch down on the first window
4240 NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4241 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4242 .build();
4243 mDispatcher->notifyMotion(downArgs);
4244
4245 window1->consumeMotionEvent(
4246 AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4247
4248 // Second window is added
4249 window2->setPreventSplitting(true);
4250 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4251
4252 // Now touch down on the window with another pointer
4253 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4254 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4255 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4256 .downTime(downArgs.downTime)
4257 .build());
4258 // Event is dropped because window2 doesn't support split touch, and window1 does.
4259
4260 // Complete the gesture
4261 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4262 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4263 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4264 .downTime(downArgs.downTime)
4265 .build());
4266 // A redundant MOVE event is generated that doesn't carry any new information
4267 window1->consumeMotionEvent(
4268 AllOf(WithMotionAction(ACTION_MOVE), WithDownTime(downArgs.downTime)));
4269 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4270 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4271 .downTime(downArgs.downTime)
4272 .build());
4273
4274 window1->consumeMotionEvent(
4275 AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4276 window1->assertNoEvents();
4277 window2->assertNoEvents();
4278}
4279
Garfield Tandf26e862020-07-01 20:18:19 -07004280TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004281 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004282 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4283 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004284 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004285 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4286 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004287 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004288
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004289 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004290
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004291 mDispatcher->onWindowInfosChanged(
4292 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004293
4294 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004296 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004297 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4298 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004299 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004300 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004301 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004302
4303 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004304 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004305 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004306 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4307 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004308 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004309 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004310 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4311 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004312
4313 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004314 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004315 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004316 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4317 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004318 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004319 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004320 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4321 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004322
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004324 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004325 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4326 AINPUT_SOURCE_MOUSE)
4327 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4328 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004329 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004330 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004331 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004332
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004334 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004335 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4336 AINPUT_SOURCE_MOUSE)
4337 .buttonState(0)
4338 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004339 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004340 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004341 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004342
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004343 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004344 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004345 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4346 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004347 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004348 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004349 windowLeft->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004350
4351 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004352 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004353 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004354 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4355 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004356 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004357 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004358 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004359
4360 // No more events
4361 windowLeft->assertNoEvents();
4362 windowRight->assertNoEvents();
4363}
4364
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004365/**
4366 * Put two fingers down (and don't release them) and click the mouse button.
4367 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4368 * currently active gesture should be canceled, and the new one should proceed.
4369 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004370TEST_F(InputDispatcherTest, TwoPointersDownMouseClick_legacy) {
4371 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004372 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004373 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4374 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004375 window->setFrame(Rect(0, 0, 600, 800));
4376
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004377 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004378
4379 const int32_t touchDeviceId = 4;
4380 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004381
4382 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004383 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4384 .deviceId(touchDeviceId)
4385 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4386 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004387
Prabir Pradhan678438e2023-04-13 19:32:51 +00004388 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4389 .deviceId(touchDeviceId)
4390 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4391 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4392 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004393 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4394 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4395
4396 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004397 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4398 .deviceId(mouseDeviceId)
4399 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4400 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4401 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004402 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4403 WithPointerCount(2u)));
4404 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4405
Prabir Pradhan678438e2023-04-13 19:32:51 +00004406 mDispatcher->notifyMotion(
4407 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4408 .deviceId(mouseDeviceId)
4409 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4410 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4411 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4412 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004413 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4414
4415 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4416 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004417 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4418 .deviceId(touchDeviceId)
4419 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4420 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4421 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004422 window->assertNoEvents();
4423}
4424
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004425/**
4426 * Put two fingers down (and don't release them) and click the mouse button.
4427 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4428 * currently active gesture should not be canceled, and the new one should proceed in parallel.
4429 */
4430TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4431 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4432 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004433 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4434 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004435 window->setFrame(Rect(0, 0, 600, 800));
4436
4437 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4438
4439 const int32_t touchDeviceId = 4;
4440 const int32_t mouseDeviceId = 6;
4441
4442 // Two pointers down
4443 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4444 .deviceId(touchDeviceId)
4445 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4446 .build());
4447
4448 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4449 .deviceId(touchDeviceId)
4450 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4451 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4452 .build());
4453 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4454 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4455
4456 // Send a series of mouse events for a mouse click
4457 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4458 .deviceId(mouseDeviceId)
4459 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4460 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4461 .build());
4462 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4463
4464 mDispatcher->notifyMotion(
4465 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4466 .deviceId(mouseDeviceId)
4467 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4468 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4469 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4470 .build());
4471 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4472
4473 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4474 // already active gesture, it should be sent normally.
4475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4476 .deviceId(touchDeviceId)
4477 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4478 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4479 .build());
4480 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4481 window->assertNoEvents();
4482}
4483
Siarhei Vishniakou07cdda92024-07-01 16:45:08 -07004484/**
4485 * A spy window sits above a window with NO_INPUT_CHANNEL. Ensure that the spy receives events even
4486 * though the window underneath should not get any events.
4487 */
4488TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowSinglePointer) {
4489 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4490
4491 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4492 ui::LogicalDisplayId::DEFAULT);
4493 spyWindow->setFrame(Rect(0, 0, 100, 100));
4494 spyWindow->setTrustedOverlay(true);
4495 spyWindow->setPreventSplitting(true);
4496 spyWindow->setSpy(true);
4497 // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4498 sp<FakeWindowHandle> inputSinkWindow =
4499 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4500 ui::LogicalDisplayId::DEFAULT);
4501 inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
4502 inputSinkWindow->setTrustedOverlay(true);
4503 inputSinkWindow->setPreventSplitting(true);
4504 inputSinkWindow->setNoInputChannel(true);
4505
4506 mDispatcher->onWindowInfosChanged(
4507 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo()}, {}, 0, 0});
4508
4509 // Tap the spy window
4510 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4511 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(51))
4512 .build());
4513 mDispatcher->notifyMotion(
4514 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4515 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4516 .build());
4517
4518 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4519 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP)));
4520 inputSinkWindow->assertNoEvents();
4521}
4522
4523/**
4524 * A spy window sits above a window with NO_INPUT_CHANNEL. Ensure that the spy receives events even
4525 * though the window underneath should not get any events.
4526 * Same test as above, but with two pointers touching instead of one.
4527 */
4528TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowTwoPointers) {
4529 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4530
4531 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4532 ui::LogicalDisplayId::DEFAULT);
4533 spyWindow->setFrame(Rect(0, 0, 100, 100));
4534 spyWindow->setTrustedOverlay(true);
4535 spyWindow->setPreventSplitting(true);
4536 spyWindow->setSpy(true);
4537 // Another window below spy that would have both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4538 sp<FakeWindowHandle> inputSinkWindow =
4539 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4540 ui::LogicalDisplayId::DEFAULT);
4541 inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
4542 inputSinkWindow->setTrustedOverlay(true);
4543 inputSinkWindow->setPreventSplitting(true);
4544 inputSinkWindow->setNoInputChannel(true);
4545
4546 mDispatcher->onWindowInfosChanged(
4547 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo()}, {}, 0, 0});
4548
4549 // Both fingers land into the spy window
4550 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4551 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(51))
4552 .build());
4553 mDispatcher->notifyMotion(
4554 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4555 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4556 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(11))
4557 .build());
4558 mDispatcher->notifyMotion(
4559 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4560 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4561 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(11))
4562 .build());
4563 mDispatcher->notifyMotion(
4564 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4565 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4566 .build());
4567
4568 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4569 spyWindow->consumeMotionPointerDown(1, WithPointerCount(2));
4570 spyWindow->consumeMotionPointerUp(1, WithPointerCount(2));
4571 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP)));
4572 inputSinkWindow->assertNoEvents();
4573}
4574
4575/** Check the behaviour for cases where input sink prevents or doesn't prevent splitting. */
4576class SpyThatPreventsSplittingWithApplicationFixture : public InputDispatcherTest,
4577 public ::testing::WithParamInterface<bool> {
4578};
4579
4580/**
4581 * Three windows:
4582 * - An application window (app window)
4583 * - A spy window that does not overlap the app window. Has PREVENT_SPLITTING flag
4584 * - A window below the spy that has NO_INPUT_CHANNEL (call it 'inputSink')
4585 *
4586 * The spy window is side-by-side with the app window. The inputSink is below the spy.
4587 * We first touch the area outside of the appWindow, but inside spyWindow.
4588 * Only the SPY window should get the DOWN event.
4589 * The spy pilfers after receiving the first DOWN event.
4590 * Next, we touch the app window.
4591 * The spy should receive POINTER_DOWN(1) (since spy is preventing splits).
4592 * Also, since the spy is already pilfering the first pointer, it will be sent the remaining new
4593 * pointers automatically, as well.
4594 * Next, the first pointer (from the spy) is lifted.
4595 * Spy should get POINTER_UP(0).
4596 * This event should not go to the app because the app never received this pointer to begin with.
4597 * Now, lift the remaining pointer and check that the spy receives UP event.
4598 *
4599 * Finally, send a new ACTION_DOWN event to the spy and check that it's received.
4600 * This test attempts to reproduce a crash in the dispatcher.
4601 */
4602TEST_P(SpyThatPreventsSplittingWithApplicationFixture, SpyThatPreventsSplittingWithApplication) {
4603 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4604
4605 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4606 ui::LogicalDisplayId::DEFAULT);
4607 spyWindow->setFrame(Rect(100, 100, 200, 200));
4608 spyWindow->setTrustedOverlay(true);
4609 spyWindow->setPreventSplitting(true);
4610 spyWindow->setSpy(true);
4611 // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4612 sp<FakeWindowHandle> inputSinkWindow =
4613 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4614 ui::LogicalDisplayId::DEFAULT);
4615 inputSinkWindow->setFrame(Rect(100, 100, 200, 200)); // directly below the spy
4616 inputSinkWindow->setTrustedOverlay(true);
4617 inputSinkWindow->setPreventSplitting(GetParam());
4618 inputSinkWindow->setNoInputChannel(true);
4619
4620 sp<FakeWindowHandle> appWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "App",
4621 ui::LogicalDisplayId::DEFAULT);
4622 appWindow->setFrame(Rect(0, 0, 100, 100));
4623
4624 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
4625 mDispatcher->onWindowInfosChanged(
4626 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo(), *appWindow->getInfo()},
4627 {},
4628 0,
4629 0});
4630
4631 // First finger lands outside of the appWindow, but inside of the spy window
4632 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4633 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
4634 .build());
4635 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4636
4637 mDispatcher->pilferPointers(spyWindow->getToken());
4638
4639 // Second finger lands in the app, and goes to the spy window. It doesn't go to the app because
4640 // the spy is already pilfering the first pointer, and this automatically grants the remaining
4641 // new pointers to the spy, as well.
4642 mDispatcher->notifyMotion(
4643 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4644 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
4645 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4646 .build());
4647
4648 spyWindow->consumeMotionPointerDown(1, WithPointerCount(2));
4649
4650 // Now lift up the first pointer
4651 mDispatcher->notifyMotion(
4652 MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
4653 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
4654 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4655 .build());
4656 spyWindow->consumeMotionPointerUp(0, WithPointerCount(2));
4657
4658 // And lift the remaining pointer!
4659 mDispatcher->notifyMotion(
4660 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4661 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4662 .build());
4663 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithPointerCount(1)));
4664
4665 // Now send a new DOWN, which should again go to spy.
4666 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4667 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
4668 .build());
4669 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4670 // The app window doesn't get any events this entire time because the spy received the events
4671 // first and pilfered, which makes all new pointers go to it as well.
4672 appWindow->assertNoEvents();
4673}
4674
4675// Behaviour should be the same regardless of whether inputSink supports splitting.
4676INSTANTIATE_TEST_SUITE_P(SpyThatPreventsSplittingWithApplication,
4677 SpyThatPreventsSplittingWithApplicationFixture, testing::Bool());
4678
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004679TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4681
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004682 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4683 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004684 spyWindow->setFrame(Rect(0, 0, 600, 800));
4685 spyWindow->setTrustedOverlay(true);
4686 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004687 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4688 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004689 window->setFrame(Rect(0, 0, 600, 800));
4690
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004691 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004692 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004693
4694 // Send mouse cursor to the window
4695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004696 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004697 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4698 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004699 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004700 .build()));
4701
4702 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4703 WithSource(AINPUT_SOURCE_MOUSE)));
4704 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4705 WithSource(AINPUT_SOURCE_MOUSE)));
4706
4707 window->assertNoEvents();
4708 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004709}
4710
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004711TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows_legacy) {
4712 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4714
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004715 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4716 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004717 spyWindow->setFrame(Rect(0, 0, 600, 800));
4718 spyWindow->setTrustedOverlay(true);
4719 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004720 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4721 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004722 window->setFrame(Rect(0, 0, 600, 800));
4723
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004724 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004725 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004726
4727 // Send mouse cursor to the window
4728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004729 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004730 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4731 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004732 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004733 .build()));
4734
4735 // Move mouse cursor
4736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004737 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004738 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4739 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004740 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004741 .build()));
4742
4743 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4744 WithSource(AINPUT_SOURCE_MOUSE)));
4745 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4746 WithSource(AINPUT_SOURCE_MOUSE)));
4747 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4748 WithSource(AINPUT_SOURCE_MOUSE)));
4749 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4750 WithSource(AINPUT_SOURCE_MOUSE)));
4751 // Touch down on the window
4752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004753 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004754 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4755 AINPUT_SOURCE_TOUCHSCREEN)
4756 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004757 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004758 .build()));
4759 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4760 WithSource(AINPUT_SOURCE_MOUSE)));
4761 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4762 WithSource(AINPUT_SOURCE_MOUSE)));
4763 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4764 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4765 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4766 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4767
4768 // pilfer the motion, retaining the gesture on the spy window.
4769 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4770 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4771 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4772
4773 // Touch UP on the window
4774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004775 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004776 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4777 AINPUT_SOURCE_TOUCHSCREEN)
4778 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004779 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004780 .build()));
4781 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4782 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4783
4784 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4785 // to send a new gesture. It should again go to both windows (spy and the window below), just
4786 // like the first gesture did, before pilfering. The window configuration has not changed.
4787
4788 // One more tap - DOWN
4789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004790 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004791 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4792 AINPUT_SOURCE_TOUCHSCREEN)
4793 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004794 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004795 .build()));
4796 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4797 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4798 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4799 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4800
4801 // Touch UP on the window
4802 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004803 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004804 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4805 AINPUT_SOURCE_TOUCHSCREEN)
4806 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004807 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004808 .build()));
4809 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4810 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4811 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4812 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4813
4814 window->assertNoEvents();
4815 spyWindow->assertNoEvents();
4816}
4817
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004818TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4819 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4820 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4821
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004822 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4823 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004824 spyWindow->setFrame(Rect(0, 0, 600, 800));
4825 spyWindow->setTrustedOverlay(true);
4826 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004827 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4828 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004829 window->setFrame(Rect(0, 0, 600, 800));
4830
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004831 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004832 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4833
4834 // Send mouse cursor to the window
4835 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4836 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4837 .build());
4838
4839 // Move mouse cursor
4840 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4841 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4842 .build());
4843
4844 window->consumeMotionEvent(
4845 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4846 spyWindow->consumeMotionEvent(
4847 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4848 window->consumeMotionEvent(
4849 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4850 spyWindow->consumeMotionEvent(
4851 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4852 // Touch down on the window
4853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4854 .deviceId(SECOND_DEVICE_ID)
4855 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4856 .build());
4857 window->consumeMotionEvent(
4858 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4859 spyWindow->consumeMotionEvent(
4860 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4861
4862 // pilfer the motion, retaining the gesture on the spy window.
4863 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4864 window->consumeMotionEvent(
4865 AllOf(WithMotionAction(ACTION_CANCEL), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4866 // Mouse hover is not pilfered
4867
4868 // Touch UP on the window
4869 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4870 .deviceId(SECOND_DEVICE_ID)
4871 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4872 .build());
4873 spyWindow->consumeMotionEvent(
4874 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4875
4876 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4877 // to send a new gesture. It should again go to both windows (spy and the window below), just
4878 // like the first gesture did, before pilfering. The window configuration has not changed.
4879
4880 // One more tap - DOWN
4881 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4882 .deviceId(SECOND_DEVICE_ID)
4883 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4884 .build());
4885 window->consumeMotionEvent(
4886 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4887 spyWindow->consumeMotionEvent(
4888 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4889
4890 // Touch UP on the window
4891 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4892 .deviceId(SECOND_DEVICE_ID)
4893 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4894 .build());
4895 window->consumeMotionEvent(
4896 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4897 spyWindow->consumeMotionEvent(
4898 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4899
4900 // Mouse movement continues normally as well
4901 // Move mouse cursor
4902 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4903 .pointer(PointerBuilder(0, ToolType::MOUSE).x(120).y(130))
4904 .build());
4905 window->consumeMotionEvent(
4906 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4907 spyWindow->consumeMotionEvent(
4908 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4909
4910 window->assertNoEvents();
4911 spyWindow->assertNoEvents();
4912}
4913
Garfield Tandf26e862020-07-01 20:18:19 -07004914// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4915// directly in this test.
4916TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004917 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004918 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4919 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004920 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004921
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004922 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004923
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004924 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004925
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004927 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004928 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4929 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004930 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004931 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004932 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004933 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004934 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004935 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004936 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4937 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004938 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004939 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004940 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4941 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004942
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004944 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004945 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4946 AINPUT_SOURCE_MOUSE)
4947 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4948 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004949 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004950 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004951 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004952
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004954 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004955 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4956 AINPUT_SOURCE_MOUSE)
4957 .buttonState(0)
4958 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004959 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004960 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004961 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004962
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004963 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004964 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004965 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4966 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004967 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004968 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004969 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004970
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004971 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4972 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4973 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004974 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004975 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4976 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004977 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004978 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004979 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004980}
4981
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004982/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004983 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4984 * is generated.
4985 */
4986TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4987 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004988 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4989 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004990 window->setFrame(Rect(0, 0, 1200, 800));
4991
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004992 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004993
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004994 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004995
4996 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004997 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004998 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4999 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005000 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005001 .build()));
5002 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5003
5004 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005005 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005006 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
5007}
5008
5009/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07005010 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
5011 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00005012TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
5013 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
5014 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07005015 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005016 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5017 ui::LogicalDisplayId::DEFAULT);
Daniel Norman7487dfa2023-08-02 16:39:45 -07005018 window->setFrame(Rect(0, 0, 1200, 800));
5019
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005020 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Daniel Norman7487dfa2023-08-02 16:39:45 -07005021
5022 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5023
5024 MotionEventBuilder hoverEnterBuilder =
5025 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5026 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
5027 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
5028 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5029 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
5030 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5031 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
5032 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5033 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5034}
5035
5036/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005037 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
5038 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005039TEST_F(InputDispatcherTest, TouchDownAfterMouseHover_legacy) {
5040 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005041 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005042 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5043 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005044 window->setFrame(Rect(0, 0, 100, 100));
5045
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005046 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005047
5048 const int32_t mouseDeviceId = 7;
5049 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005050
5051 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00005052 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5053 .deviceId(mouseDeviceId)
5054 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
5055 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005056 window->consumeMotionEvent(
5057 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
5058
5059 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00005060 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5061 .deviceId(touchDeviceId)
5062 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5063 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005064
5065 window->consumeMotionEvent(
5066 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
5067 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
5068}
5069
5070/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005071 * If mouse is hovering when the touch goes down, the hovering should not be stopped.
5072 */
5073TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
5074 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5075 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005076 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5077 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005078 window->setFrame(Rect(0, 0, 100, 100));
5079
5080 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5081
5082 const int32_t mouseDeviceId = 7;
5083 const int32_t touchDeviceId = 4;
5084
5085 // Start hovering with the mouse
5086 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5087 .deviceId(mouseDeviceId)
5088 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
5089 .build());
5090 window->consumeMotionEvent(
5091 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
5092
5093 // Touch goes down
5094 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5095 .deviceId(touchDeviceId)
5096 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5097 .build());
5098 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
5099}
5100
5101/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005102 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005103 * The tap causes a HOVER_EXIT event to be generated because the current event
5104 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005105 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005106TEST_F(InputDispatcherTest, MouseHoverAndTouchTap_legacy) {
5107 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005108 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005109 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5110 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005111 window->setFrame(Rect(0, 0, 100, 100));
5112
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005113 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005114 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
5115 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
5116 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005117 ASSERT_NO_FATAL_FAILURE(
5118 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
5119 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005120
5121 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005122 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5123 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5124 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005125 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005126 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
5127 WithSource(AINPUT_SOURCE_MOUSE))));
5128
5129 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005130 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
5131 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
5132
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005133 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5134 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5135 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005136 ASSERT_NO_FATAL_FAILURE(
5137 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
5138 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
5139}
5140
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005141/**
5142 * Send a mouse hover event followed by a tap from touchscreen.
5143 * The tap causes a HOVER_EXIT event to be generated because the current event
5144 * stream's source has been switched.
5145 */
5146TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
5147 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5148 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005149 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5150 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005151 window->setFrame(Rect(0, 0, 100, 100));
5152
5153 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5154 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
5155 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
5156 .build());
5157
5158 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
5159 WithSource(AINPUT_SOURCE_MOUSE)));
5160
5161 // Tap on the window
5162 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5163 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5164 .build());
5165
5166 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
5167 WithSource(AINPUT_SOURCE_MOUSE)));
5168
5169 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
5170 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
5171
5172 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5173 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5174 .build());
5175
5176 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
5177 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
5178}
5179
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005180TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
5181 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5182 sp<FakeWindowHandle> windowDefaultDisplay =
5183 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005184 ui::LogicalDisplayId::DEFAULT);
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005185 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
5186 sp<FakeWindowHandle> windowSecondDisplay =
5187 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
5188 SECOND_DISPLAY_ID);
5189 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
5190
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005191 mDispatcher->onWindowInfosChanged(
5192 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005193
5194 // Set cursor position in window in default display and check that hover enter and move
5195 // events are generated.
5196 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005197 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005198 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5199 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005200 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005201 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005202 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005203 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005204
5205 // Remove all windows in secondary display and check that no event happens on window in
5206 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005207 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
5208
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005209 windowDefaultDisplay->assertNoEvents();
5210
5211 // Move cursor position in window in default display and check that only hover move
5212 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005213 mDispatcher->onWindowInfosChanged(
5214 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005216 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005217 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5218 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005219 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005220 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005221 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005222 windowDefaultDisplay->consumeMotionEvent(
5223 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
5224 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005225 windowDefaultDisplay->assertNoEvents();
5226}
5227
Garfield Tan00f511d2019-06-12 16:55:40 -07005228TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07005229 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07005230
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005231 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
5232 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005233 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005234 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
5235 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005236 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07005237
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005238 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tan00f511d2019-06-12 16:55:40 -07005239
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005240 mDispatcher->onWindowInfosChanged(
5241 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07005242
5243 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
5244 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005246 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005247 ui::LogicalDisplayId::DEFAULT, {610, 400}, {599, 400}));
5248 windowLeft->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005249 windowRight->assertNoEvents();
5250}
5251
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005252TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005253 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005254 sp<FakeWindowHandle> window =
5255 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5256 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07005257 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005258
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005259 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005260 setFocusedWindow(window);
5261
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005262 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005263
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005264 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005265
5266 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005267 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005268
5269 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
5270 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005271 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005272 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005273}
5274
5275TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005276 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005277 sp<FakeWindowHandle> window =
5278 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5279 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005280
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005281 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005282
Prabir Pradhan678438e2023-04-13 19:32:51 +00005283 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005284 AINPUT_SOURCE_TOUCHSCREEN,
5285 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005286
5287 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005288 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005289
5290 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
5291 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005292 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005293 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005294 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005295}
5296
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005297TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
5298 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005299 sp<FakeWindowHandle> window =
5300 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5301 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005302
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005303 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005304
5305 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5306 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
5307 .build());
5308
5309 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5310
5311 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
5312 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
5313 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5314
5315 // After the device has been reset, a new hovering stream can be sent to the window
5316 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5317 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
5318 .build());
5319 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5320}
5321
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005322TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
5323 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005324 sp<FakeWindowHandle> window =
5325 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5326 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005327 window->setFocusable(true);
5328
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005329 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005330 setFocusedWindow(window);
5331
5332 window->consumeFocusEvent(true);
5333
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005334 const NotifyKeyArgs keyArgs =
5335 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005336 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
5337 const nsecs_t injectTime = keyArgs.eventTime;
5338 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005339 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005340 // The dispatching time should be always greater than or equal to intercept key timeout.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005341 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005342 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
5343 std::chrono::nanoseconds(interceptKeyTimeout).count());
5344}
5345
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005346/**
5347 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
5348 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005349TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
5350 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005351 sp<FakeWindowHandle> window =
5352 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5353 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005354 window->setFocusable(true);
5355
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005356 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005357 setFocusedWindow(window);
5358
5359 window->consumeFocusEvent(true);
5360
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005361 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
5362 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005363
5364 // Set a value that's significantly larger than the default consumption timeout. If the
5365 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
5366 mFakePolicy->setInterceptKeyTimeout(600ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005367 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005368 // Window should receive key event immediately when same key up.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005369 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005370}
5371
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005372/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005373 * Two windows. First is a regular window. Second does not overlap with the first, and has
5374 * WATCH_OUTSIDE_TOUCH.
5375 * Both windows are owned by the same UID.
5376 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
5377 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
5378 */
5379TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
5380 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005381 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5382 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005383 window->setFrame(Rect{0, 0, 100, 100});
5384
5385 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005386 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005387 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005388 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5389 outsideWindow->setWatchOutsideTouch(true);
5390 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005391 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005392
5393 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005394 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005395 AINPUT_SOURCE_TOUCHSCREEN,
5396 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005397 window->consumeMotionDown();
5398 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
5399 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
5400 outsideWindow->consumeMotionEvent(
5401 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005402
5403 // Ensure outsideWindow doesn't get any more events for the gesture.
5404 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005405 ui::LogicalDisplayId::DEFAULT, {PointF{51, 51}}));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005406 window->consumeMotionMove();
5407 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005408}
5409
5410/**
Linnan Liccf6ce32024-04-11 20:32:13 +08005411 * Three windows:
5412 * - Left window
5413 * - Right window
5414 * - Outside window(watch for ACTION_OUTSIDE events)
5415 * The windows "left" and "outside" share the same owner, the window "right" has a different owner,
5416 * In order to allow the outside window can receive the ACTION_OUTSIDE events, the outside window is
5417 * positioned above the "left" and "right" windows, and it doesn't overlap with them.
5418 *
5419 * First, device A report a down event landed in the right window, the outside window can receive
5420 * an ACTION_OUTSIDE event that with zeroed coordinates, the device B report a down event landed
5421 * in the left window, the outside window can receive an ACTION_OUTSIDE event the with valid
5422 * coordinates, after these, device A and device B continue report MOVE event, the right and left
5423 * window can receive it, but outside window event can't receive it.
5424 */
5425TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinatesWhenMultiDevice) {
5426 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5427 sp<FakeWindowHandle> leftWindow =
5428 sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005429 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005430 leftWindow->setFrame(Rect{0, 0, 100, 100});
5431 leftWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5432
5433 sp<FakeWindowHandle> outsideWindow =
5434 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005435 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005436 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5437 outsideWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5438 outsideWindow->setWatchOutsideTouch(true);
5439
5440 std::shared_ptr<FakeApplicationHandle> anotherApplication =
5441 std::make_shared<FakeApplicationHandle>();
5442 sp<FakeWindowHandle> rightWindow =
5443 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Right Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005444 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005445 rightWindow->setFrame(Rect{100, 0, 200, 100});
5446 rightWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
5447
5448 // OutsideWindow must be above left window and right window to receive ACTION_OUTSIDE events
5449 // when left window or right window is tapped
5450 mDispatcher->onWindowInfosChanged(
5451 {{*outsideWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()},
5452 {},
5453 0,
5454 0});
5455
5456 const DeviceId deviceA = 9;
5457 const DeviceId deviceB = 3;
5458
5459 // Tap on right window use device A
5460 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5461 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5462 .deviceId(deviceA)
5463 .build());
5464 leftWindow->assertNoEvents();
5465 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5466 // Right window is belonged to another owner, so outsideWindow should receive ACTION_OUTSIDE
5467 // with zeroed coords.
5468 outsideWindow->consumeMotionEvent(
5469 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceA), WithCoords(0, 0)));
5470
5471 // Tap on left window use device B
5472 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5473 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5474 .deviceId(deviceB)
5475 .build());
5476 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5477 rightWindow->assertNoEvents();
5478 // Because new gesture down on the left window that has the same owner with outside Window, the
5479 // outside Window should receive the ACTION_OUTSIDE with coords.
5480 outsideWindow->consumeMotionEvent(
5481 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceB), WithCoords(-50, -50)));
5482
5483 // Ensure that windows that can only accept outside do not receive remaining gestures
5484 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5485 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
5486 .deviceId(deviceA)
5487 .build());
5488 leftWindow->assertNoEvents();
5489 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA)));
5490
5491 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5492 .pointer(PointerBuilder(0, ToolType::FINGER).x(51).y(51))
5493 .deviceId(deviceB)
5494 .build());
5495 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
5496 rightWindow->assertNoEvents();
5497 outsideWindow->assertNoEvents();
5498}
5499
5500/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005501 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
5502 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
5503 * ACTION_OUTSIDE event is sent per gesture.
5504 */
5505TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
5506 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
5507 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005508 sp<FakeWindowHandle> window =
5509 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5510 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005511 window->setWatchOutsideTouch(true);
5512 window->setFrame(Rect{0, 0, 100, 100});
5513 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005514 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005515 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005516 secondWindow->setFrame(Rect{100, 100, 200, 200});
5517 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005518 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005519 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005520 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005521 mDispatcher->onWindowInfosChanged(
5522 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005523
5524 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005525 mDispatcher->notifyMotion(
5526 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5527 ui::LogicalDisplayId::DEFAULT, {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005528 window->assertNoEvents();
5529 secondWindow->assertNoEvents();
5530
5531 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
5532 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005533 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005534 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005535 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005536 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
5537 window->consumeMotionEvent(
5538 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005539 secondWindow->consumeMotionDown();
5540 thirdWindow->assertNoEvents();
5541
5542 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
5543 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005544 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005545 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5546 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005547 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005548 window->assertNoEvents();
5549 secondWindow->consumeMotionMove();
5550 thirdWindow->consumeMotionDown();
5551}
5552
Prabir Pradhan814fe082022-07-22 20:22:18 +00005553TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
5554 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005555 sp<FakeWindowHandle> window =
5556 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5557 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005558 window->setFocusable(true);
5559
Patrick Williamsd828f302023-04-28 17:52:08 -05005560 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005561 setFocusedWindow(window);
5562
5563 window->consumeFocusEvent(true);
5564
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005565 const NotifyKeyArgs keyDown =
5566 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
5567 const NotifyKeyArgs keyUp =
5568 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005569 mDispatcher->notifyKey(keyDown);
5570 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005571
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005572 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5573 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005574
5575 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05005576 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005577
5578 window->consumeFocusEvent(false);
5579
Prabir Pradhan678438e2023-04-13 19:32:51 +00005580 mDispatcher->notifyKey(keyDown);
5581 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005582 window->assertNoEvents();
5583}
5584
Arthur Hung96483742022-11-15 03:30:48 +00005585TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
5586 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005587 sp<FakeWindowHandle> window =
5588 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5589 ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005590 // Ensure window is non-split and have some transform.
5591 window->setPreventSplitting(true);
5592 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05005593 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00005594
5595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005596 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5597 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung96483742022-11-15 03:30:48 +00005598 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005599 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005600
5601 const MotionEvent secondFingerDownEvent =
5602 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005603 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung96483742022-11-15 03:30:48 +00005604 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005605 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5606 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00005607 .build();
5608 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005609 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00005610 InputEventInjectionSync::WAIT_FOR_RESULT))
5611 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5612
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005613 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
5614 ASSERT_NE(nullptr, event);
5615 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
5616 EXPECT_EQ(70, event->getX(0)); // 50 + 20
5617 EXPECT_EQ(90, event->getY(0)); // 50 + 40
5618 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
5619 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00005620}
5621
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005622/**
5623 * Two windows: a splittable and a non-splittable.
5624 * The non-splittable window shouldn't receive any "incomplete" gestures.
5625 * Send the first pointer to the splittable window, and then touch the non-splittable window.
5626 * The second pointer should be dropped because the initial window is splittable, so it won't get
5627 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
5628 * "incomplete" gestures.
5629 */
5630TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
5631 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5632 sp<FakeWindowHandle> leftWindow =
5633 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005634 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005635 leftWindow->setPreventSplitting(false);
5636 leftWindow->setFrame(Rect(0, 0, 100, 100));
5637 sp<FakeWindowHandle> rightWindow =
5638 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005639 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005640 rightWindow->setPreventSplitting(true);
5641 rightWindow->setFrame(Rect(100, 100, 200, 200));
5642 mDispatcher->onWindowInfosChanged(
5643 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5644
5645 // Touch down on left, splittable window
5646 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5647 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5648 .build());
5649 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5650
5651 mDispatcher->notifyMotion(
5652 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5653 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5654 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
5655 .build());
5656 leftWindow->assertNoEvents();
5657 rightWindow->assertNoEvents();
5658}
5659
Siarhei Vishniakou96204462024-07-13 23:59:47 -07005660/**
5661 * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a
5662 * down event to the right window. Device B sends a down event to the left window, and then a
5663 * POINTER_DOWN event to the right window. However, since the left window prevents splitting, the
5664 * POINTER_DOWN event should only go to the left window, and not to the right window.
5665 * This test attempts to reproduce a crash.
5666 */
5667TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) {
5668 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5669 sp<FakeWindowHandle> leftWindow =
5670 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)",
5671 ui::LogicalDisplayId::DEFAULT);
5672 leftWindow->setFrame(Rect(0, 0, 100, 100));
5673 leftWindow->setPreventSplitting(true);
5674
5675 sp<FakeWindowHandle> rightWindow =
5676 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
5677 ui::LogicalDisplayId::DEFAULT);
5678 rightWindow->setFrame(Rect(100, 0, 200, 100));
5679
5680 mDispatcher->onWindowInfosChanged(
5681 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5682
5683 const DeviceId deviceA = 9;
5684 const DeviceId deviceB = 3;
5685 // Touch the right window with device A
5686 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5687 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5688 .deviceId(deviceA)
5689 .build());
5690 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5691 // Touch the left window with device B
5692 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5693 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5694 .deviceId(deviceB)
5695 .build());
5696 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5697 // Send a second pointer from device B to the right window. It shouldn't go to the right window
5698 // because the left window prevents splitting.
5699 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5700 .deviceId(deviceB)
5701 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5702 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
5703 .build());
5704 leftWindow->consumeMotionPointerDown(1, WithDeviceId(deviceB));
5705
5706 // Finish the gesture for both devices
5707 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5708 .deviceId(deviceB)
5709 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5710 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
5711 .build());
5712 leftWindow->consumeMotionPointerUp(1, WithDeviceId(deviceB));
5713 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5714 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5715 .deviceId(deviceB)
5716 .build());
5717 leftWindow->consumeMotionEvent(
5718 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithPointerId(0, 0)));
5719 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5720 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5721 .deviceId(deviceA)
5722 .build());
5723 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA)));
5724}
5725
Harry Cuttsb166c002023-05-09 13:06:05 +00005726TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
5727 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005728 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5729 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005730 window->setFrame(Rect(0, 0, 400, 400));
5731 sp<FakeWindowHandle> trustedOverlay =
5732 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005733 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005734 trustedOverlay->setSpy(true);
5735 trustedOverlay->setTrustedOverlay(true);
5736
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005737 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005738
5739 // Start a three-finger touchpad swipe
5740 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5741 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5742 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5743 .build());
5744 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5745 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5746 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5747 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5748 .build());
5749 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5750 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5751 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5752 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5753 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5754 .build());
5755
5756 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5757 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5758 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
5759
5760 // Move the swipe a bit
5761 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5762 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5763 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5764 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5765 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5766 .build());
5767
5768 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5769
5770 // End the swipe
5771 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5772 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5773 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5774 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5775 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5776 .build());
5777 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5778 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5779 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5780 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5781 .build());
5782 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5783 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5784 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5785 .build());
5786
5787 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
5788 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5789 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
5790
5791 window->assertNoEvents();
5792}
5793
5794TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
5795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005796 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5797 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005798 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005799 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005800
5801 // Start a three-finger touchpad swipe
5802 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5803 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5804 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5805 .build());
5806 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5807 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5808 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5809 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5810 .build());
5811 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5812 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5813 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5814 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5815 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5816 .build());
5817
5818 // Move the swipe a bit
5819 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5820 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5821 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5822 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5823 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5824 .build());
5825
5826 // End the swipe
5827 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5828 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5829 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5830 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5831 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5832 .build());
5833 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5834 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5835 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5836 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5837 .build());
5838 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5839 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5840 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5841 .build());
5842
5843 window->assertNoEvents();
5844}
5845
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005846/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005847 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
5848 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005849 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005850 */
5851TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
5852 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005853 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5854 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005855 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005856 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005857
5858 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
5859 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5860 .downTime(baseTime + 10)
5861 .eventTime(baseTime + 10)
5862 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5863 .build());
5864
5865 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5866
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005867 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005868 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005869
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005870 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005871
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005872 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5873 .downTime(baseTime + 10)
5874 .eventTime(baseTime + 30)
5875 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5876 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5877 .build());
5878
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005879 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5880
5881 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005882 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5883 .downTime(baseTime + 10)
5884 .eventTime(baseTime + 40)
5885 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5886 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5887 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005888
5889 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5890
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005891 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5892 .downTime(baseTime + 10)
5893 .eventTime(baseTime + 50)
5894 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5895 .build());
5896
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005897 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
5898
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005899 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5900 .downTime(baseTime + 60)
5901 .eventTime(baseTime + 60)
5902 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
5903 .build());
5904
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005905 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005906}
5907
5908/**
Hu Guo771a7692023-09-17 20:51:08 +08005909 * When there are multiple screens, such as screen projection to TV or screen recording, if the
5910 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
5911 * its coordinates should be converted by the transform of the windows of target screen.
5912 */
5913TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
5914 // This case will create a window and a spy window on the default display and mirror
5915 // window on the second display. cancel event is sent through spy window pilferPointers
5916 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5917
5918 sp<FakeWindowHandle> spyWindowDefaultDisplay =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005919 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
5920 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005921 spyWindowDefaultDisplay->setTrustedOverlay(true);
5922 spyWindowDefaultDisplay->setSpy(true);
5923
5924 sp<FakeWindowHandle> windowDefaultDisplay =
5925 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005926 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005927 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
5928
5929 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
5930 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
5931
5932 // Add the windows to the dispatcher
5933 mDispatcher->onWindowInfosChanged(
5934 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
5935 *windowSecondDisplay->getInfo()},
5936 {},
5937 0,
5938 0});
5939
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005940 // Send down to ui::LogicalDisplayId::DEFAULT
Hu Guo771a7692023-09-17 20:51:08 +08005941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005942 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5943 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Hu Guo771a7692023-09-17 20:51:08 +08005944 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5945
5946 spyWindowDefaultDisplay->consumeMotionDown();
5947 windowDefaultDisplay->consumeMotionDown();
5948
5949 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
5950
5951 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005952 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
5953 ASSERT_NE(nullptr, event);
5954 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08005955
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005956 // The cancel event is sent to windowDefaultDisplay of the ui::LogicalDisplayId::DEFAULT
5957 // display, so the coordinates of the cancel are converted by windowDefaultDisplay's transform,
5958 // the x and y coordinates are both 100, otherwise if the cancel event is sent to
5959 // windowSecondDisplay of SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005960 EXPECT_EQ(100, event->getX(0));
5961 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08005962}
5963
5964/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005965 * Ensure the correct coordinate spaces are used by InputDispatcher.
5966 *
5967 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5968 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5969 * space.
5970 */
5971class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5972public:
5973 void SetUp() override {
5974 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005975 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005976 }
5977
Linnan Li13bf76a2024-05-05 19:18:02 +08005978 void addDisplayInfo(ui::LogicalDisplayId displayId, const ui::Transform& transform) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005979 gui::DisplayInfo info;
5980 info.displayId = displayId;
5981 info.transform = transform;
5982 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005983 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005984 }
5985
5986 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5987 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005988 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005989 }
5990
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005991 void removeAllWindowsAndDisplays() {
5992 mDisplayInfos.clear();
5993 mWindowInfos.clear();
5994 }
5995
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005996 // Set up a test scenario where the display has a scaled projection and there are two windows
5997 // on the display.
5998 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5999 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
6000 // respectively.
6001 ui::Transform displayTransform;
6002 displayTransform.set(2, 0, 0, 4);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006003 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006004
6005 std::shared_ptr<FakeApplicationHandle> application =
6006 std::make_shared<FakeApplicationHandle>();
6007
6008 // Add two windows to the display. Their frames are represented in the display space.
6009 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006010 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006011 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006012 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
6013 addWindow(firstWindow);
6014
6015 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006016 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006017 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006018 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
6019 addWindow(secondWindow);
6020 return {std::move(firstWindow), std::move(secondWindow)};
6021 }
6022
6023private:
6024 std::vector<gui::DisplayInfo> mDisplayInfos;
6025 std::vector<gui::WindowInfo> mWindowInfos;
6026};
6027
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006028TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006029 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6030 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006031 // selected so that if the hit test was performed with the point and the bounds being in
6032 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006033 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006034 AINPUT_SOURCE_TOUCHSCREEN,
6035 ui::LogicalDisplayId::DEFAULT, {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006036
6037 firstWindow->consumeMotionDown();
6038 secondWindow->assertNoEvents();
6039}
6040
6041// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
6042// the event should be treated as being in the logical display space.
6043TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
6044 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6045 // Send down to the first window. The point is represented in the logical display space. The
6046 // point is selected so that if the hit test was done in logical display space, then it would
6047 // end up in the incorrect window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006048 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006049 PointF{75 * 2, 55 * 4});
6050
6051 firstWindow->consumeMotionDown();
6052 secondWindow->assertNoEvents();
6053}
6054
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006055// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
6056// event should be treated as being in the logical display space.
6057TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
6058 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6059
6060 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6061 ui::Transform injectedEventTransform;
6062 injectedEventTransform.set(matrix);
6063 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
6064 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
6065
6066 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006067 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006068 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006069 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006070 .x(untransformedPoint.x)
6071 .y(untransformedPoint.y))
6072 .build();
6073 event.transform(matrix);
6074
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006075 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006076 InputEventInjectionSync::WAIT_FOR_RESULT);
6077
6078 firstWindow->consumeMotionDown();
6079 secondWindow->assertNoEvents();
6080}
6081
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006082TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
6083 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6084
6085 // Send down to the second window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006086 mDispatcher->notifyMotion(
6087 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6088 ui::LogicalDisplayId::DEFAULT, {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006089
6090 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006091 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
6092 ASSERT_NE(nullptr, event);
6093 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006094
6095 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006096 EXPECT_EQ(300, event->getRawX(0));
6097 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006098
6099 // Ensure that the x and y values are in the window's coordinate space.
6100 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
6101 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006102 EXPECT_EQ(100, event->getX(0));
6103 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006104}
6105
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006106TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
6107 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6108 // The monitor will always receive events in the logical display's coordinate space, because
6109 // it does not have a window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006110 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ui::LogicalDisplayId::DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006111
6112 // Send down to the first window.
6113 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006114 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006115 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6116 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6117
6118 // Second pointer goes down on second window.
6119 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006120 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006121 {PointF{50, 100}, PointF{150, 220}}));
6122 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
6123 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
6124 {1, PointF{300, 880}}};
6125 monitor.consumeMotionEvent(
6126 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
6127
6128 mDispatcher->cancelCurrentTouch();
6129
6130 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
6131 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
6132 monitor.consumeMotionEvent(
6133 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
6134}
6135
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006136TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
6137 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6138
6139 // Send down to the first window.
6140 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006141 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006142 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6143
6144 // The pointer is transferred to the second window, and the second window receives it in the
6145 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006146 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006147 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
6148 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
6149}
6150
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006151TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
6152 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6153
6154 // Send hover move to the second window, and ensure it shows up as hover enter.
6155 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006156 ui::LogicalDisplayId::DEFAULT,
6157 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006158 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6159 WithCoords(100, 80), WithRawCoords(300, 880)));
6160
6161 // Touch down at the same location and ensure a hover exit is synthesized.
6162 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006163 ui::LogicalDisplayId::DEFAULT,
6164 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006165 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6166 WithRawCoords(300, 880)));
6167 secondWindow->consumeMotionEvent(
6168 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
6169 secondWindow->assertNoEvents();
6170 firstWindow->assertNoEvents();
6171}
6172
Prabir Pradhan453ae732023-10-13 14:30:14 +00006173// Same as above, but while the window is being mirrored.
6174TEST_F(InputDispatcherDisplayProjectionTest,
6175 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
6176 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6177
6178 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6179 ui::Transform secondDisplayTransform;
6180 secondDisplayTransform.set(matrix);
6181 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
6182
6183 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
6184 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
6185 addWindow(secondWindowClone);
6186
6187 // Send hover move to the second window, and ensure it shows up as hover enter.
6188 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006189 ui::LogicalDisplayId::DEFAULT,
6190 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00006191 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6192 WithCoords(100, 80), WithRawCoords(300, 880)));
6193
6194 // Touch down at the same location and ensure a hover exit is synthesized for the correct
6195 // display.
6196 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006197 ui::LogicalDisplayId::DEFAULT,
6198 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00006199 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6200 WithRawCoords(300, 880)));
6201 secondWindow->consumeMotionEvent(
6202 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
6203 secondWindow->assertNoEvents();
6204 firstWindow->assertNoEvents();
6205}
6206
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006207TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
6208 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6209
6210 // Send hover enter to second window
6211 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006212 ui::LogicalDisplayId::DEFAULT,
6213 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006214 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6215 WithCoords(100, 80), WithRawCoords(300, 880)));
6216
6217 mDispatcher->cancelCurrentTouch();
6218
6219 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6220 WithRawCoords(300, 880)));
6221 secondWindow->assertNoEvents();
6222 firstWindow->assertNoEvents();
6223}
6224
Prabir Pradhan453ae732023-10-13 14:30:14 +00006225// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00006226TEST_F(InputDispatcherDisplayProjectionTest,
6227 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
6228 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6229
6230 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6231 ui::Transform secondDisplayTransform;
6232 secondDisplayTransform.set(matrix);
6233 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
6234
6235 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
6236 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
6237 addWindow(secondWindowClone);
6238
6239 // Send hover enter to second window
6240 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006241 ui::LogicalDisplayId::DEFAULT,
6242 {PointF{150, 220}}));
Prabir Pradhan16463382023-10-12 23:03:19 +00006243 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6244 WithCoords(100, 80), WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006245 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00006246
6247 mDispatcher->cancelCurrentTouch();
6248
6249 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
6250 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6251 WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006252 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00006253 secondWindow->assertNoEvents();
6254 firstWindow->assertNoEvents();
6255}
6256
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006257/** Ensure consistent behavior of InputDispatcher in all orientations. */
6258class InputDispatcherDisplayOrientationFixture
6259 : public InputDispatcherDisplayProjectionTest,
6260 public ::testing::WithParamInterface<ui::Rotation> {};
6261
6262// This test verifies the touchable region of a window for all rotations of the display by tapping
6263// in different locations on the display, specifically points close to the four corners of a
6264// window.
6265TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
6266 constexpr static int32_t displayWidth = 400;
6267 constexpr static int32_t displayHeight = 800;
6268
6269 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6270
6271 const auto rotation = GetParam();
6272
6273 // Set up the display with the specified rotation.
6274 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6275 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6276 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6277 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6278 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006279 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006280
6281 // Create a window with its bounds determined in the logical display.
6282 const Rect frameInLogicalDisplay(100, 100, 200, 300);
6283 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006284 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6285 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006286 window->setFrame(frameInDisplay, displayTransform);
6287 addWindow(window);
6288
6289 // The following points in logical display space should be inside the window.
6290 static const std::array<vec2, 4> insidePoints{
6291 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6292 for (const auto pointInsideWindow : insidePoints) {
6293 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
6294 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006295 mDispatcher->notifyMotion(
6296 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6297 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006298 window->consumeMotionDown();
6299
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006300 mDispatcher->notifyMotion(
6301 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6302 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006303 window->consumeMotionUp();
6304 }
6305
6306 // The following points in logical display space should be outside the window.
6307 static const std::array<vec2, 5> outsidePoints{
6308 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6309 for (const auto pointOutsideWindow : outsidePoints) {
6310 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
6311 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006312 mDispatcher->notifyMotion(
6313 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6314 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006315
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006316 mDispatcher->notifyMotion(
6317 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6318 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006319 }
6320 window->assertNoEvents();
6321}
6322
Linnan Li5e5645e2024-03-05 14:43:05 +00006323// This test verifies the occlusion detection for all rotations of the display by tapping
6324// in different locations on the display, specifically points close to the four corners of a
6325// window.
6326TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) {
6327 constexpr static int32_t displayWidth = 400;
6328 constexpr static int32_t displayHeight = 800;
6329
6330 std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication =
6331 std::make_shared<FakeApplicationHandle>();
6332 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6333
6334 const auto rotation = GetParam();
6335
6336 // Set up the display with the specified rotation.
6337 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6338 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6339 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6340 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6341 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006342 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Linnan Li5e5645e2024-03-05 14:43:05 +00006343
6344 // Create a window that not trusted.
6345 const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
6346
6347 const Rect untrustedWindowFrameInDisplay =
6348 displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay);
6349
6350 sp<FakeWindowHandle> untrustedWindow =
6351 sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006352 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006353 untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
6354 untrustedWindow->setTrustedOverlay(false);
6355 untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
6356 untrustedWindow->setTouchable(false);
6357 untrustedWindow->setAlpha(1.0f);
6358 untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
6359 addWindow(untrustedWindow);
6360
6361 // Create a simple app window below the untrusted window.
6362 const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600);
6363 const Rect simpleAppWindowFrameInDisplay =
6364 displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay);
6365
6366 sp<FakeWindowHandle> simpleAppWindow =
6367 sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006368 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006369 simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
6370 simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
6371 addWindow(simpleAppWindow);
6372
6373 // The following points in logical display space should be inside the untrusted window, so
6374 // the simple window could not receive events that coordinate is these point.
6375 static const std::array<vec2, 4> untrustedPoints{
6376 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6377
6378 for (const auto untrustedPoint : untrustedPoints) {
6379 const vec2 p = displayTransform.inverse().transform(untrustedPoint);
6380 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006381 mDispatcher->notifyMotion(
6382 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6383 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6384 mDispatcher->notifyMotion(
6385 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6386 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Linnan Li5e5645e2024-03-05 14:43:05 +00006387 }
6388 untrustedWindow->assertNoEvents();
6389 simpleAppWindow->assertNoEvents();
6390 // The following points in logical display space should be outside the untrusted window, so
6391 // the simple window should receive events that coordinate is these point.
6392 static const std::array<vec2, 5> trustedPoints{
6393 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6394 for (const auto trustedPoint : trustedPoints) {
6395 const vec2 p = displayTransform.inverse().transform(trustedPoint);
6396 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006397 mDispatcher->notifyMotion(
6398 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6399 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6400 simpleAppWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006401 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006402 mDispatcher->notifyMotion(
6403 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6404 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6405 simpleAppWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006406 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6407 }
6408 untrustedWindow->assertNoEvents();
6409}
6410
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006411// Run the precision tests for all rotations.
6412INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
6413 InputDispatcherDisplayOrientationFixture,
6414 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6415 ui::ROTATION_270),
6416 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6417 return ftl::enum_string(testParamInfo.param);
6418 });
6419
Siarhei Vishniakou18050092021-09-01 13:32:49 -07006420using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
6421 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006422
6423class TransferTouchFixture : public InputDispatcherTest,
6424 public ::testing::WithParamInterface<TransferFunction> {};
6425
6426TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07006427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006428
6429 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006430 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006431 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006432 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006433 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006434 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006435 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006436 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006437 sp<FakeWindowHandle> wallpaper =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006438 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
6439 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006440 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006441 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006442 mDispatcher->onWindowInfosChanged(
6443 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00006444 setFocusedWindow(firstWindow);
6445 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006446
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));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006451
Svet Ganov5d3bc372020-01-26 23:11:07 -08006452 // Only the first window should get the down event
6453 firstWindow->consumeMotionDown();
6454 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006455 wallpaper->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006456 // Dispatcher reports pointer down outside focus for the wallpaper
6457 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006458
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006459 // Transfer touch to the second window
6460 TransferFunction f = GetParam();
6461 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6462 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006463 // The first window gets cancel and the second gets down
6464 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006465 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6466 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6467 wallpaper->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006468 // There should not be any changes to the focused window when transferring touch
6469 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006470
6471 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006472 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006473 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00006474 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08006475 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006476 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6477 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006478 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006479}
6480
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006481/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00006482 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
6483 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
6484 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006485 * natural to the user.
6486 * In this test, we are sending a pointer to both spy window and first window. We then try to
6487 * transfer touch to the second window. The dispatcher should identify the first window as the
6488 * one that should lose the gesture, and therefore the action should be to move the gesture from
6489 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006490 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
6491 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006492 */
6493TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
6494 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6495
6496 // Create a couple of windows + a spy window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006497 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6498 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006499 spyWindow->setTrustedOverlay(true);
6500 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006501 sp<FakeWindowHandle> firstWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "First",
6502 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006503 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006504 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
6505 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006506
6507 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006508 mDispatcher->onWindowInfosChanged(
6509 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006510
6511 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006512 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006513 AINPUT_SOURCE_TOUCHSCREEN,
6514 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006515 // Only the first window and spy should get the down event
6516 spyWindow->consumeMotionDown();
6517 firstWindow->consumeMotionDown();
6518
6519 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00006520 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006521 TransferFunction f = GetParam();
6522 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6523 ASSERT_TRUE(success);
6524 // The first window gets cancel and the second gets down
6525 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006526 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6527 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006528
6529 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006530 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006531 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006532 // The first window gets no events and the second+spy get up
6533 firstWindow->assertNoEvents();
6534 spyWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006535 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6536 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006537}
6538
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006539TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006540 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006541
6542 PointF touchPoint = {10, 10};
6543
6544 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006545 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006546 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006547 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006548 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006549 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006550 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006551 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006552 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006553
6554 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006555 mDispatcher->onWindowInfosChanged(
6556 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006557
6558 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006559 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006560 AINPUT_SOURCE_TOUCHSCREEN,
6561 ui::LogicalDisplayId::DEFAULT, {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006562 // Only the first window should get the down event
6563 firstWindow->consumeMotionDown();
6564 secondWindow->assertNoEvents();
6565
6566 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006567 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006568 ui::LogicalDisplayId::DEFAULT,
6569 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006570 // Only the first window should get the pointer down event
6571 firstWindow->consumeMotionPointerDown(1);
6572 secondWindow->assertNoEvents();
6573
6574 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006575 TransferFunction f = GetParam();
6576 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6577 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006578 // The first window gets cancel and the second gets down and pointer down
6579 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006580 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6581 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6582 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006583 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006584
6585 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006586 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006587 ui::LogicalDisplayId::DEFAULT,
6588 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006589 // The first window gets nothing and the second gets pointer up
6590 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00006591 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
6592 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
6593 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
6594 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006595
6596 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006597 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006598 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006599 // The first window gets nothing and the second gets up
6600 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006601 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6602 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006603}
6604
Arthur Hungc539dbb2022-12-08 07:45:36 +00006605TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
6606 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6607
6608 // Create a couple of windows
6609 sp<FakeWindowHandle> firstWindow =
6610 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006611 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006612 firstWindow->setDupTouchToWallpaper(true);
6613 sp<FakeWindowHandle> secondWindow =
6614 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006615 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006616 secondWindow->setDupTouchToWallpaper(true);
6617
6618 sp<FakeWindowHandle> wallpaper1 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006619 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1",
6620 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006621 wallpaper1->setIsWallpaper(true);
6622
6623 sp<FakeWindowHandle> wallpaper2 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006624 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2",
6625 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006626 wallpaper2->setIsWallpaper(true);
6627 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006628 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
6629 *secondWindow->getInfo(), *wallpaper2->getInfo()},
6630 {},
6631 0,
6632 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00006633
6634 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006635 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006636 AINPUT_SOURCE_TOUCHSCREEN,
6637 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006638
6639 // Only the first window should get the down event
6640 firstWindow->consumeMotionDown();
6641 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006642 wallpaper1->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006643 wallpaper2->assertNoEvents();
6644
6645 // Transfer touch focus to the second window
6646 TransferFunction f = GetParam();
6647 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6648 ASSERT_TRUE(success);
6649
6650 // The first window gets cancel and the second gets down
6651 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006652 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6653 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6654 wallpaper1->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
6655 wallpaper2->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006656 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006657
6658 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006659 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006660 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006661 // The first window gets no events and the second gets up
6662 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006663 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6664 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006665 wallpaper1->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006666 wallpaper2->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006667 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006668}
6669
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006670// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00006671// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006672// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006673INSTANTIATE_TEST_SUITE_P(
6674 InputDispatcherTransferFunctionTests, TransferTouchFixture,
6675 ::testing::Values(
6676 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
6677 sp<IBinder> destChannelToken) {
6678 return dispatcher->transferTouchOnDisplay(destChannelToken,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006679 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006680 },
6681 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
6682 sp<IBinder> to) {
6683 return dispatcher->transferTouchGesture(from, to,
6684 /*isDragAndDrop=*/false);
6685 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006686
Prabir Pradhan367f3432024-02-13 23:05:58 +00006687TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006688 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006689
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006690 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006691 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006692 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006693 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006694
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006695 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006696 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006697 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006698 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006699
6700 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006701 mDispatcher->onWindowInfosChanged(
6702 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006703
6704 PointF pointInFirst = {300, 200};
6705 PointF pointInSecond = {300, 600};
6706
6707 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006708 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006709 AINPUT_SOURCE_TOUCHSCREEN,
6710 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006711 // Only the first window should get the down event
6712 firstWindow->consumeMotionDown();
6713 secondWindow->assertNoEvents();
6714
6715 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006716 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006717 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006718 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006719 // The first window gets a move and the second a down
6720 firstWindow->consumeMotionMove();
6721 secondWindow->consumeMotionDown();
6722
Prabir Pradhan367f3432024-02-13 23:05:58 +00006723 // Transfer touch to the second window
6724 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006725 // The first window gets cancel and the new gets pointer down (it already saw down)
6726 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006727 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006728 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006729
6730 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006731 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006732 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006733 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006734 // The first window gets nothing and the second gets pointer up
6735 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00006736 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
6737 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
6738 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
6739 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006740
6741 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006742 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006743 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006744 // The first window gets nothing and the second gets up
6745 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006746 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6747 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006748}
6749
Prabir Pradhan367f3432024-02-13 23:05:58 +00006750// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
6751// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
6752// receiving touch is not supported, so the touch should continue on those windows and the
6753// transferred-to window should get nothing.
6754TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006755 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6756
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006757 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006758 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006759 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006760 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006761
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006762 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006763 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006764 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006765 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006766
6767 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006768 mDispatcher->onWindowInfosChanged(
6769 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006770
6771 PointF pointInFirst = {300, 200};
6772 PointF pointInSecond = {300, 600};
6773
6774 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006775 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006776 AINPUT_SOURCE_TOUCHSCREEN,
6777 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006778 // Only the first window should get the down event
6779 firstWindow->consumeMotionDown();
6780 secondWindow->assertNoEvents();
6781
6782 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006783 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006784 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006785 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006786 // The first window gets a move and the second a down
6787 firstWindow->consumeMotionMove();
6788 secondWindow->consumeMotionDown();
6789
6790 // Transfer touch focus to the second window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006791 const bool transferred = mDispatcher->transferTouchOnDisplay(secondWindow->getToken(),
6792 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006793 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006794 ASSERT_FALSE(transferred);
6795 firstWindow->assertNoEvents();
6796 secondWindow->assertNoEvents();
6797
6798 // The rest of the dispatch should proceed as normal
6799 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006800 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006801 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006802 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006803 // The first window gets MOVE and the second gets pointer up
6804 firstWindow->consumeMotionMove();
6805 secondWindow->consumeMotionUp();
6806
6807 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006808 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006809 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006810 // The first window gets nothing and the second gets up
6811 firstWindow->consumeMotionUp();
6812 secondWindow->assertNoEvents();
6813}
6814
Arthur Hungabbb9d82021-09-01 14:52:30 +00006815// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00006816// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00006817// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006818TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006819 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6820 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006821 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6822 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006823 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006824 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006825 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6826 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006827 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006828
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006829 sp<FakeWindowHandle> mirrorWindowInPrimary =
6830 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006831 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006832
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006833 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006834 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006835
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006836 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006837 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006838
6839 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006840 mDispatcher->onWindowInfosChanged(
6841 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6842 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6843 *secondWindowInPrimary->getInfo()},
6844 {},
6845 0,
6846 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006847
6848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006849 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6850 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006851 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6852
6853 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006854 firstWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006855
Prabir Pradhan367f3432024-02-13 23:05:58 +00006856 // Transfer touch
6857 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
6858 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006859 // The first window gets cancel.
6860 firstWindowInPrimary->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006861 secondWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006862 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006863
6864 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006865 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006866 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006867 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6868 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006869 secondWindowInPrimary->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006870 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006871
6872 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006873 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006874 {150, 50}))
6875 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6876 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006877 secondWindowInPrimary->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6878 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006879}
6880
Prabir Pradhan367f3432024-02-13 23:05:58 +00006881// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
6882// 'transferTouchOnDisplay' api.
6883TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006884 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6885 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006886 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6887 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006888 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006889 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006890 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6891 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006892 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006893
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006894 sp<FakeWindowHandle> mirrorWindowInPrimary =
6895 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006896 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006897
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006898 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006899 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006900
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006901 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006902 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006903
6904 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006905 mDispatcher->onWindowInfosChanged(
6906 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6907 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6908 *secondWindowInPrimary->getInfo()},
6909 {},
6910 0,
6911 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006912
6913 // Touch on second display.
6914 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006915 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6916 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006917 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6918
6919 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006920 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006921
6922 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00006923 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
6924 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006925
6926 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006927 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006928 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
6929 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006930
6931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006932 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006933 SECOND_DISPLAY_ID, {150, 50}))
6934 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006935 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006936 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
6937 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006938
6939 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006940 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006941 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006942 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006943 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006944}
6945
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006946TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006947 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006948 sp<FakeWindowHandle> window =
6949 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6950 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006951
Vishnu Nair47074b82020-08-14 11:54:47 -07006952 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006953 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006954 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006955
6956 window->consumeFocusEvent(true);
6957
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006958 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006959
6960 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006961 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006962
6963 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006964 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006965 mFakePolicy->assertUserActivityPoked();
6966}
6967
6968TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
6969 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006970 sp<FakeWindowHandle> window =
6971 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6972 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006973
6974 window->setDisableUserActivity(true);
6975 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006976 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006977 setFocusedWindow(window);
6978
6979 window->consumeFocusEvent(true);
6980
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006981 mDispatcher->notifyKey(
6982 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006983
6984 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006985 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006986
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006987 // Should have not poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006988 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006989 mFakePolicy->assertUserActivityNotPoked();
6990}
6991
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006992TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyConsumedKey) {
Josep del Riob3981622023-04-18 15:49:45 +00006993 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006994 sp<FakeWindowHandle> window =
6995 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6996 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006997
6998 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006999 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00007000 setFocusedWindow(window);
7001
7002 window->consumeFocusEvent(true);
7003
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007004 mFakePolicy->setConsumeKeyBeforeDispatching(true);
7005
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007006 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007007 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00007008 mDispatcher->waitForIdle();
7009
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007010 // Key is not passed down
Josep del Riob3981622023-04-18 15:49:45 +00007011 window->assertNoEvents();
7012
7013 // Should have poked user activity
7014 mFakePolicy->assertUserActivityPoked();
7015}
7016
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007017TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserActivity) {
Josep del Riob3981622023-04-18 15:49:45 +00007018 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007019 sp<FakeWindowHandle> window =
7020 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7021 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007022
7023 window->setDisableUserActivity(true);
7024 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007025 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00007026 setFocusedWindow(window);
7027
7028 window->consumeFocusEvent(true);
7029
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007030 mFakePolicy->setConsumeKeyBeforeDispatching(true);
7031
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007032 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007033 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00007034 mDispatcher->waitForIdle();
7035
7036 // System key is not passed down
7037 window->assertNoEvents();
7038
7039 // Should have poked user activity
7040 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007041}
7042
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007043class DisableUserActivityInputDispatcherTest : public InputDispatcherTest,
7044 public ::testing::WithParamInterface<bool> {};
7045
7046TEST_P(DisableUserActivityInputDispatcherTest, NotPassedToUserUserActivity) {
7047 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7048 sp<FakeWindowHandle> window =
7049 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7050 ui::LogicalDisplayId::DEFAULT);
7051
7052 window->setDisableUserActivity(GetParam());
7053
7054 window->setFocusable(true);
7055 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7056 setFocusedWindow(window);
7057
7058 window->consumeFocusEvent(true);
7059
7060 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7061 .keyCode(AKEYCODE_A)
7062 .policyFlags(0)
7063 .build());
7064 mDispatcher->waitForIdle();
7065
7066 // Key is not passed down
7067 window->assertNoEvents();
7068
7069 // Should not have poked user activity
7070 mFakePolicy->assertUserActivityNotPoked();
7071}
7072
7073INSTANTIATE_TEST_CASE_P(DisableUserActivity, DisableUserActivityInputDispatcherTest,
7074 ::testing::Bool());
7075
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007076TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
7077 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007078 sp<FakeWindowHandle> window =
7079 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7080 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007081
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007082 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007083
7084 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007085 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007086 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007087 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7088
7089 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007090 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007091
7092 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00007093 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007094 mFakePolicy->assertUserActivityPoked();
7095}
7096
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007097TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007098 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007099 sp<FakeWindowHandle> window =
7100 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7101 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007102
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007103 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007104
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007105 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007106 mDispatcher->waitForIdle();
7107
7108 window->assertNoEvents();
7109}
7110
7111// If a window is touchable, but does not have focus, it should receive motion events, but not keys
7112TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07007113 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007114 sp<FakeWindowHandle> window =
7115 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7116 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007117
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007118 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007119
7120 // Send key
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007121 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007122 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00007123 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007124 AINPUT_SOURCE_TOUCHSCREEN,
7125 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007126
7127 // Window should receive only the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007128 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007129 window->assertNoEvents(); // Key event or focus event will not be received
7130}
7131
arthurhungea3f4fc2020-12-21 23:18:53 +08007132TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
7133 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7134
arthurhungea3f4fc2020-12-21 23:18:53 +08007135 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007136 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007137 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08007138 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08007139
arthurhungea3f4fc2020-12-21 23:18:53 +08007140 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007141 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007142 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08007143 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08007144
7145 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007146 mDispatcher->onWindowInfosChanged(
7147 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08007148
7149 PointF pointInFirst = {300, 200};
7150 PointF pointInSecond = {300, 600};
7151
7152 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007153 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007154 AINPUT_SOURCE_TOUCHSCREEN,
7155 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08007156 // Only the first window should get the down event
7157 firstWindow->consumeMotionDown();
7158 secondWindow->assertNoEvents();
7159
7160 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007161 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007162 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007163 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08007164 // The first window gets a move and the second a down
7165 firstWindow->consumeMotionMove();
7166 secondWindow->consumeMotionDown();
7167
7168 // Send pointer cancel to the second window
7169 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007170 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
7171 ui::LogicalDisplayId::DEFAULT, {pointInFirst, pointInSecond});
arthurhungea3f4fc2020-12-21 23:18:53 +08007172 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00007173 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08007174 // The first window gets move and the second gets cancel.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007175 firstWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
7176 secondWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
arthurhungea3f4fc2020-12-21 23:18:53 +08007177
7178 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007179 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007180 ui::LogicalDisplayId::DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08007181 // The first window gets up and the second gets nothing.
7182 firstWindow->consumeMotionUp();
7183 secondWindow->assertNoEvents();
7184}
7185
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007186TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
7187 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7188
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007189 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
7190 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007191 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007192 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
7193 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
7194 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
7195
Harry Cutts33476232023-01-30 19:57:29 +00007196 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007197 window->assertNoEvents();
7198 mDispatcher->waitForIdle();
7199}
7200
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007201using InputDispatcherMonitorTest = InputDispatcherTest;
7202
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007203/**
7204 * Two entities that receive touch: A window, and a global monitor.
7205 * The touch goes to the window, and then the window disappears.
7206 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
7207 * for the monitor, as well.
7208 * 1. foregroundWindow
7209 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
7210 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007211TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007212 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007213 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7214 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007215
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007216 FakeMonitorReceiver monitor =
7217 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007218
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007219 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007220 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007221 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7222 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007223 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7224
7225 // Both the foreground window and the global monitor should receive the touch down
7226 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007227 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007228
7229 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007230 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007231 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007232 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7233
7234 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007235 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007236
7237 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007238 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007239 window->consumeMotionCancel();
7240 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
7241
7242 // If more events come in, there will be no more foreground window to send them to. This will
7243 // cause a cancel for the monitor, as well.
7244 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007245 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007246 ui::LogicalDisplayId::DEFAULT, {120, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007247 << "Injection should fail because the window was removed";
7248 window->assertNoEvents();
7249 // Global monitor now gets the cancel
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007250 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007251}
7252
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007253TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07007254 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007255 sp<FakeWindowHandle> window =
7256 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7257 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007258 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007259
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007260 FakeMonitorReceiver monitor =
7261 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007262
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007263 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007264 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7265 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007266 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007267 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7268 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007269}
7270
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007271TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007272 FakeMonitorReceiver monitor =
7273 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007274
Chris Yea209fde2020-07-22 13:54:51 -07007275 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007276 sp<FakeWindowHandle> window =
7277 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7278 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007279 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007280
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007282 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7283 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007284 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007285 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7286 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007287
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007288 // Pilfer pointers from the monitor.
7289 // This should not do anything and the window should continue to receive events.
7290 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00007291
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007293 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007294 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007295 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007296
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007297 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
7298 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007299}
7300
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007301TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07007302 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007303 sp<FakeWindowHandle> window =
7304 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7305 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007306 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07007307 window->setWindowOffset(20, 40);
7308 window->setWindowTransform(0, 1, -1, 0);
7309
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007310 FakeMonitorReceiver monitor =
7311 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07007312
7313 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007314 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7315 ui::LogicalDisplayId::DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07007316 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007317 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007318 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
7319 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07007320 // Even though window has transform, gesture monitor must not.
7321 ASSERT_EQ(ui::Transform(), event->getTransform());
7322}
7323
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007324TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00007325 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007326 FakeMonitorReceiver monitor =
7327 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00007328
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007329 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007330 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7331 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007332 << "Injection should fail if there is a monitor, but no touchable window";
7333 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00007334}
7335
Linnan Lid8150952024-01-26 18:07:17 +00007336/**
7337 * Two displays
7338 * The first monitor has a foreground window, a monitor
7339 * The second window has only one monitor.
7340 * We first inject a Down event into the first display, this injection should succeed and both
7341 * the foreground window and monitor should receive a down event, then inject a Down event into
7342 * the second display as well, this injection should fail, at this point, the first display
7343 * window and monitor should not receive a cancel or any other event.
7344 * Continue to inject Move and UP events to the first display, the events should be received
7345 * normally by the foreground window and monitor.
7346 */
7347TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
7348 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007349 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7350 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007351
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 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7357 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007358 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7359 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007360 << "The down event injected into the first display should succeed";
7361
7362 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007363 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007364
7365 ASSERT_EQ(InputEventInjectionResult::FAILED,
7366 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7367 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007368 << "The down event injected into the second display should fail since there's no "
7369 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007370
7371 // Continue to inject event to first display.
7372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7373 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007374 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007375 << "The move event injected into the first display should succeed";
7376
7377 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007378 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007379
7380 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007381 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007382 {110, 220}))
7383 << "The up event injected into the first display should succeed";
7384
7385 window->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007386 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007387
7388 window->assertNoEvents();
7389 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007390 secondMonitor.assertNoEvents();
7391}
7392
7393/**
7394 * Two displays
7395 * There is a monitor and foreground window on each display.
7396 * First, we inject down events into each of the two displays, at this point, the foreground windows
7397 * and monitors on both displays should receive down events.
7398 * At this point, the foreground window of the second display goes away, the gone window should
7399 * receive the cancel event, and the other windows and monitors should not receive any events.
7400 * Inject a move event into the second display. At this point, the injection should fail because
7401 * the second display no longer has a foreground window. At this point, the monitor on the second
7402 * display should receive a cancel event, and any windows or monitors on the first display should
7403 * not receive any events, and any subsequent injection of events into the second display should
7404 * also fail.
7405 * Continue to inject events into the first display, and the events should all be injected
7406 * successfully and received normally.
7407 */
7408TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
7409 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007410 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7411 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007412 sp<FakeWindowHandle> secondWindow =
7413 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
7414 SECOND_DISPLAY_ID);
7415
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007416 FakeMonitorReceiver monitor =
7417 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007418 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7419
7420 // There is a foreground window on both displays.
7421 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007423 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7424 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007425 << "The down event injected into the first display should succeed";
7426
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007427 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7428 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007429
7430 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7431 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7432 {100, 200}))
7433 << "The down event injected into the second display should succeed";
7434
Linnan Lid8150952024-01-26 18:07:17 +00007435 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
7436 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
7437
7438 // Now second window is gone away.
7439 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7440
7441 // The gone window should receive a cancel, and the monitor on the second display should not
7442 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00007443 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
7444 secondMonitor.assertNoEvents();
7445
7446 ASSERT_EQ(InputEventInjectionResult::FAILED,
7447 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7448 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007449 << "The move event injected into the second display should fail because there's no "
7450 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007451 // Now the monitor on the second display should receive a cancel event.
7452 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00007453
7454 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7455 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007456 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007457 << "The move event injected into the first display should succeed";
7458
7459 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007460 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007461
7462 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007463 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7464 {110, 220}))
7465 << "The up event injected into the second display should fail because there's no "
7466 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007467
7468 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007469 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007470 {110, 220}))
7471 << "The up event injected into the first display should succeed";
7472
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007473 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
7474 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007475
Linnan Lid8150952024-01-26 18:07:17 +00007476 window->assertNoEvents();
7477 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007478 secondWindow->assertNoEvents();
7479 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007480}
7481
7482/**
7483 * One display with transform
7484 * There is a foreground window and a monitor on the display
7485 * Inject down event and move event sequentially, the foreground window and monitor can receive down
7486 * event and move event, then let the foreground window go away, the foreground window receives
7487 * cancel event, inject move event again, the monitor receives cancel event, all the events received
7488 * by the monitor should be with the same transform as the display
7489 */
7490TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
7491 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007492 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7493 ui::LogicalDisplayId::DEFAULT);
7494 FakeMonitorReceiver monitor =
7495 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007496
7497 ui::Transform transform;
7498 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7499
7500 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007501 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Linnan Lid8150952024-01-26 18:07:17 +00007502 displayInfo.transform = transform;
7503
7504 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
7505
7506 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007507 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7508 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007509 << "The down event injected should succeed";
7510
7511 window->consumeMotionDown();
7512 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
7513 EXPECT_EQ(transform, downMotionEvent->getTransform());
7514 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
7515
7516 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7517 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007518 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007519 << "The move event injected should succeed";
7520
7521 window->consumeMotionMove();
7522 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
7523 EXPECT_EQ(transform, moveMotionEvent->getTransform());
7524 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
7525
7526 // Let foreground window gone
7527 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
7528
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007529 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00007530 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00007531
7532 ASSERT_EQ(InputEventInjectionResult::FAILED,
7533 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007534 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007535 << "The move event injected should failed";
7536 // Now foreground should not receive any events, but monitor should receive a cancel event
7537 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00007538 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
7539 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007540 EXPECT_EQ(ui::LogicalDisplayId::DEFAULT, cancelMotionEvent->getDisplayId());
Linnan Lid8150952024-01-26 18:07:17 +00007541 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
7542
7543 // Other event inject to this display should fail.
7544 ASSERT_EQ(InputEventInjectionResult::FAILED,
7545 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007546 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007547 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00007548 window->assertNoEvents();
7549 monitor.assertNoEvents();
7550}
7551
chaviw81e2bb92019-12-18 15:03:51 -08007552TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007553 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007554 sp<FakeWindowHandle> window =
7555 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7556 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007557
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007558 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08007559
7560 NotifyMotionArgs motionArgs =
7561 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007562 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007563
Prabir Pradhan678438e2023-04-13 19:32:51 +00007564 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08007565 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007566 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007567
7568 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08007569 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08007570 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7571 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
7572 motionArgs.pointerCoords[0].getX() - 10);
7573
Prabir Pradhan678438e2023-04-13 19:32:51 +00007574 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007575 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08007576}
7577
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007578/**
7579 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
7580 * the device default right away. In the test scenario, we check both the default value,
7581 * and the action of enabling / disabling.
7582 */
7583TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07007584 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007585 sp<FakeWindowHandle> window =
7586 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7587 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08007588 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007589
7590 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007591 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007592 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007593
7594 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007595 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007596 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007597 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007598
7599 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007600 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007601 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007602 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007603
7604 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007605 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007606 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007607 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07007608 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007609 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007610 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007611 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007612
7613 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007614 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007615 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007616 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007617
7618 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007619 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007620 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007621 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07007622 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007623 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007624 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007625 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007626
7627 window->assertNoEvents();
7628}
7629
Gang Wange9087892020-01-07 12:17:14 -05007630TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007631 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007632 sp<FakeWindowHandle> window =
7633 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7634 ui::LogicalDisplayId::DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05007635
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007636 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007637 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05007638
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007639 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007640 setFocusedWindow(window);
7641
Harry Cutts33476232023-01-30 19:57:29 +00007642 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05007643
Prabir Pradhan678438e2023-04-13 19:32:51 +00007644 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
7645 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05007646
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007647 std::unique_ptr<KeyEvent> event = window->consumeKey();
7648 ASSERT_NE(event, nullptr);
7649 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05007650 ASSERT_NE(verified, nullptr);
7651 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
7652
7653 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
7654 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
7655 ASSERT_EQ(keyArgs.source, verified->source);
7656 ASSERT_EQ(keyArgs.displayId, verified->displayId);
7657
7658 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
7659
7660 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05007661 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007662 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05007663 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
7664 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
7665 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
7666 ASSERT_EQ(0, verifiedKey.repeatCount);
7667}
7668
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007669TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007670 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007671 sp<FakeWindowHandle> window =
7672 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7673 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007674
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007675 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007676
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007677 ui::Transform transform;
7678 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7679
7680 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007681 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007682 displayInfo.transform = transform;
7683
Patrick Williamsd828f302023-04-28 17:52:08 -05007684 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007685
Prabir Pradhan678438e2023-04-13 19:32:51 +00007686 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007687 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007688 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007689 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007690
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007691 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
7692 ASSERT_NE(nullptr, event);
7693 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007694 ASSERT_NE(verified, nullptr);
7695 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
7696
7697 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
7698 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
7699 EXPECT_EQ(motionArgs.source, verified->source);
7700 EXPECT_EQ(motionArgs.displayId, verified->displayId);
7701
7702 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
7703
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007704 const vec2 rawXY =
7705 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
7706 motionArgs.pointerCoords[0].getXYValue());
7707 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
7708 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007709 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007710 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007711 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007712 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
7713 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
7714}
7715
chaviw09c8d2d2020-08-24 15:48:26 -07007716/**
7717 * Ensure that separate calls to sign the same data are generating the same key.
7718 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
7719 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
7720 * tests.
7721 */
7722TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
7723 KeyEvent event = getTestKeyEvent();
7724 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7725
7726 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
7727 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
7728 ASSERT_EQ(hmac1, hmac2);
7729}
7730
7731/**
7732 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
7733 */
7734TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
7735 KeyEvent event = getTestKeyEvent();
7736 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7737 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
7738
7739 verifiedEvent.deviceId += 1;
7740 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7741
7742 verifiedEvent.source += 1;
7743 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7744
7745 verifiedEvent.eventTimeNanos += 1;
7746 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7747
Linnan Li13bf76a2024-05-05 19:18:02 +08007748 verifiedEvent.displayId = ui::LogicalDisplayId{verifiedEvent.displayId.val() + 1};
chaviw09c8d2d2020-08-24 15:48:26 -07007749 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7750
7751 verifiedEvent.action += 1;
7752 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7753
7754 verifiedEvent.downTimeNanos += 1;
7755 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7756
7757 verifiedEvent.flags += 1;
7758 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7759
7760 verifiedEvent.keyCode += 1;
7761 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7762
7763 verifiedEvent.scanCode += 1;
7764 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7765
7766 verifiedEvent.metaState += 1;
7767 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7768
7769 verifiedEvent.repeatCount += 1;
7770 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7771}
7772
Vishnu Nair958da932020-08-21 17:12:37 -07007773TEST_F(InputDispatcherTest, SetFocusedWindow) {
7774 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007775 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7776 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007777 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007778 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7779 ui::LogicalDisplayId::DEFAULT);
7780 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007781
7782 // Top window is also focusable but is not granted focus.
7783 windowTop->setFocusable(true);
7784 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007785 mDispatcher->onWindowInfosChanged(
7786 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007787 setFocusedWindow(windowSecond);
7788
7789 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007790 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007791 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007792
7793 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007794 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007795 windowTop->assertNoEvents();
7796}
7797
7798TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
7799 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007800 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7801 ui::LogicalDisplayId::DEFAULT);
7802 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007803
7804 window->setFocusable(true);
7805 // Release channel for window is no longer valid.
7806 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007807 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007808 setFocusedWindow(window);
7809
7810 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007811 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007812
7813 // window channel is invalid, so it should not receive any input event.
7814 window->assertNoEvents();
7815}
7816
7817TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
7818 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007819 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7820 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007821 window->setFocusable(false);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007822 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007823
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007824 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007825 setFocusedWindow(window);
7826
7827 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007828 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007829
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007830 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07007831 window->assertNoEvents();
7832}
7833
7834TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
7835 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007836 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7837 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007838 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007839 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7840 ui::LogicalDisplayId::DEFAULT);
7841 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007842
7843 windowTop->setFocusable(true);
7844 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007845 mDispatcher->onWindowInfosChanged(
7846 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007847 setFocusedWindow(windowTop);
7848 windowTop->consumeFocusEvent(true);
7849
Chavi Weingarten847e8512023-03-29 00:26:09 +00007850 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007851 mDispatcher->onWindowInfosChanged(
7852 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007853 windowSecond->consumeFocusEvent(true);
7854 windowTop->consumeFocusEvent(false);
7855
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007857 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007858
7859 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007860 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007861}
7862
Chavi Weingarten847e8512023-03-29 00:26:09 +00007863TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07007864 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007865 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7866 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007867 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007868 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7869 ui::LogicalDisplayId::DEFAULT);
7870 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007871
7872 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00007873 windowSecond->setFocusable(false);
7874 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007875 mDispatcher->onWindowInfosChanged(
7876 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00007877 setFocusedWindow(windowTop);
7878 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07007879
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007880 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00007881 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007882
7883 // Event should be dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007884 windowTop->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007885 windowSecond->assertNoEvents();
7886}
7887
7888TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
7889 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007890 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7891 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007892 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007893 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007894 ui::LogicalDisplayId::DEFAULT);
7895 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007896
7897 window->setFocusable(true);
7898 previousFocusedWindow->setFocusable(true);
7899 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007900 mDispatcher->onWindowInfosChanged(
7901 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007902 setFocusedWindow(previousFocusedWindow);
7903 previousFocusedWindow->consumeFocusEvent(true);
7904
7905 // Requesting focus on invisible window takes focus from currently focused window.
7906 setFocusedWindow(window);
7907 previousFocusedWindow->consumeFocusEvent(false);
7908
7909 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007911 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007912 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007913
7914 // Window does not get focus event or key down.
7915 window->assertNoEvents();
7916
7917 // Window becomes visible.
7918 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007919 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007920
7921 // Window receives focus event.
7922 window->consumeFocusEvent(true);
7923 // Focused window receives key down.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007924 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007925}
7926
Vishnu Nair599f1412021-06-21 10:39:58 -07007927TEST_F(InputDispatcherTest, DisplayRemoved) {
7928 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007929 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "window",
7930 ui::LogicalDisplayId::DEFAULT);
7931 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair599f1412021-06-21 10:39:58 -07007932
7933 // window is granted focus.
7934 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007935 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07007936 setFocusedWindow(window);
7937 window->consumeFocusEvent(true);
7938
7939 // When a display is removed window loses focus.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007940 mDispatcher->displayRemoved(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07007941 window->consumeFocusEvent(false);
7942}
7943
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007944/**
7945 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
7946 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
7947 * of the 'slipperyEnterWindow'.
7948 *
7949 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
7950 * a way so that the touched location is no longer covered by the top window.
7951 *
7952 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
7953 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
7954 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
7955 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
7956 * with ACTION_DOWN).
7957 * Thus, the touch has been transferred from the top window into the bottom window, because the top
7958 * window moved itself away from the touched location and had Flag::SLIPPERY.
7959 *
7960 * Even though the top window moved away from the touched location, it is still obscuring the bottom
7961 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
7962 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
7963 *
7964 * In this test, we ensure that the event received by the bottom window has
7965 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
7966 */
7967TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007968 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007969 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007970
7971 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007972 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007973
7974 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007975 sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7976 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007977 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007978 // Make sure this one overlaps the bottom window
7979 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
7980 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
7981 // one. Windows with the same owner are not considered to be occluding each other.
7982 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
7983
7984 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007985 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7986 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007987 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
7988
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007989 mDispatcher->onWindowInfosChanged(
7990 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007991
7992 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00007993 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007994 AINPUT_SOURCE_TOUCHSCREEN,
7995 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007996 slipperyExitWindow->consumeMotionDown();
7997 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007998 mDispatcher->onWindowInfosChanged(
7999 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008000
Prabir Pradhan678438e2023-04-13 19:32:51 +00008001 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008002 AINPUT_SOURCE_TOUCHSCREEN,
8003 ui::LogicalDisplayId::DEFAULT, {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008004
8005 slipperyExitWindow->consumeMotionCancel();
8006
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008007 slipperyEnterWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008008 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8009}
8010
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008011/**
8012 * Two windows, one on the left and another on the right. The left window is slippery. The right
8013 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
8014 * touch moves from the left window into the right window, the gesture should continue to go to the
8015 * left window. Touch shouldn't slip because the right window can't receive touches. This test
8016 * reproduces a crash.
8017 */
8018TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
8019 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8020
8021 sp<FakeWindowHandle> leftSlipperyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008022 sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
8023 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008024 leftSlipperyWindow->setSlippery(true);
8025 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
8026
8027 sp<FakeWindowHandle> rightDropTouchesWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008028 sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
8029 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008030 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
8031 rightDropTouchesWindow->setDropInput(true);
8032
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008033 mDispatcher->onWindowInfosChanged(
8034 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008035
8036 // Start touch in the left window
8037 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8038 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8039 .build());
8040 leftSlipperyWindow->consumeMotionDown();
8041
8042 // And move it into the right window
8043 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8044 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8045 .build());
8046
8047 // Since the right window isn't eligible to receive input, touch does not slip.
8048 // The left window continues to receive the gesture.
8049 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
8050 rightDropTouchesWindow->assertNoEvents();
8051}
8052
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008053/**
8054 * A single window is on screen first. Touch is injected into that window. Next, a second window
8055 * appears. Since the first window is slippery, touch will move from the first window to the second.
8056 */
8057TEST_F(InputDispatcherTest, InjectedTouchSlips) {
8058 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8059 sp<FakeWindowHandle> originalWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008060 sp<FakeWindowHandle>::make(application, mDispatcher, "Original",
8061 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008062 originalWindow->setFrame(Rect(0, 0, 200, 200));
8063 originalWindow->setSlippery(true);
8064
8065 sp<FakeWindowHandle> appearingWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008066 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing",
8067 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008068 appearingWindow->setFrame(Rect(0, 0, 200, 200));
8069
8070 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
8071
8072 // Touch down on the original window
8073 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8074 injectMotionEvent(*mDispatcher,
8075 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8076 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
8077 .build()));
8078 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8079
8080 // Now, a new window appears. This could be, for example, a notification shade that appears
8081 // after user starts to drag down on the launcher window.
8082 mDispatcher->onWindowInfosChanged(
8083 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
8084 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8085 injectMotionEvent(*mDispatcher,
8086 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8087 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
8088 .build()));
8089 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8090 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8092 injectMotionEvent(*mDispatcher,
8093 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8094 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
8095 .build()));
8096 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
8097
8098 originalWindow->assertNoEvents();
8099 appearingWindow->assertNoEvents();
8100}
8101
Linnan Li49b2b202024-04-12 12:46:40 +08008102/**
8103 * Three windows:
8104 * - left window, which has FLAG_SLIPPERY, so it supports slippery exit
8105 * - right window
8106 * - spy window
8107 * The three windows do not overlap.
8108 *
8109 * We have two devices reporting events:
8110 * - Device A reports ACTION_DOWN, which lands in the left window
8111 * - Device B reports ACTION_DOWN, which lands in the spy window.
8112 * - Now, device B reports ACTION_MOVE events which move to the right window.
8113 *
8114 * The right window should not receive any events because the spy window is not a foreground window,
8115 * and also it does not support slippery touches.
8116 */
8117TEST_F(InputDispatcherTest, MultiDeviceSpyWindowSlipTest) {
8118 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8119 sp<FakeWindowHandle> leftWindow =
8120 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008121 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008122 leftWindow->setFrame(Rect(0, 0, 100, 100));
8123 leftWindow->setSlippery(true);
8124
8125 sp<FakeWindowHandle> rightWindow =
8126 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008127 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008128 rightWindow->setFrame(Rect(100, 0, 200, 100));
8129
8130 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008131 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8132 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008133 spyWindow->setFrame(Rect(200, 0, 300, 100));
8134 spyWindow->setSpy(true);
8135 spyWindow->setTrustedOverlay(true);
8136
8137 mDispatcher->onWindowInfosChanged(
8138 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *spyWindow->getInfo()}, {}, 0, 0});
8139
8140 const DeviceId deviceA = 9;
8141 const DeviceId deviceB = 3;
8142
8143 // Tap on left window with device A
8144 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8145 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8146 .deviceId(deviceA)
8147 .build());
8148 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8149
8150 // Tap on spy window with device B
8151 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8152 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
8153 .deviceId(deviceB)
8154 .build());
8155 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8156
8157 // Move to right window with device B. Touches should not slip to the right window, because spy
8158 // window is not a foreground window, and it does not have FLAG_SLIPPERY
8159 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8160 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8161 .deviceId(deviceB)
8162 .build());
8163 leftWindow->assertNoEvents();
8164 rightWindow->assertNoEvents();
8165 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
8166}
8167
8168/**
8169 * Three windows arranged horizontally and without any overlap.
8170 * The left and right windows have FLAG_SLIPPERY. The middle window does not have any special flags.
8171 *
8172 * We have two devices reporting events:
8173 * - Device A reports ACTION_DOWN which lands in the left window
8174 * - Device B reports ACTION_DOWN which lands in the right window
8175 * - Device B reports ACTION_MOVE that shifts to the middle window.
8176 * This should cause touches for Device B to slip from the right window to the middle window.
8177 * The right window should receive ACTION_CANCEL for device B and the
8178 * middle window should receive down event for Device B.
8179 * If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
8180 */
8181TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
Siarhei Vishniakoudd56df12024-05-20 14:56:38 -07008182 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
Linnan Li49b2b202024-04-12 12:46:40 +08008183 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8184 sp<FakeWindowHandle> leftWindow =
8185 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008186 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008187 leftWindow->setFrame(Rect(0, 0, 100, 100));
8188 leftWindow->setSlippery(true);
8189
8190 sp<FakeWindowHandle> middleWindow =
8191 sp<FakeWindowHandle>::make(application, mDispatcher, "middle window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008192 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008193 middleWindow->setFrame(Rect(100, 0, 200, 100));
8194
8195 sp<FakeWindowHandle> rightWindow =
8196 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008197 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008198 rightWindow->setFrame(Rect(200, 0, 300, 100));
8199 rightWindow->setSlippery(true);
8200
8201 mDispatcher->onWindowInfosChanged(
8202 {{*leftWindow->getInfo(), *middleWindow->getInfo(), *rightWindow->getInfo()},
8203 {},
8204 0,
8205 0});
8206
8207 const DeviceId deviceA = 9;
8208 const DeviceId deviceB = 3;
8209
8210 // Tap on left window with device A
8211 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8212 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8213 .deviceId(deviceA)
8214 .build());
8215 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8216
8217 // Tap on right window with device B
8218 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8219 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
8220 .deviceId(deviceB)
8221 .build());
8222 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8223
8224 // Move to middle window with device B. Touches should slip to middle window, because right
8225 // window is a foreground window that's associated with device B and has FLAG_SLIPPERY.
8226 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8227 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8228 .deviceId(deviceB)
8229 .build());
8230 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
8231 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8232
8233 // Move to middle window with device A. Touches should slip to middle window, because left
8234 // window is a foreground window that's associated with device A and has FLAG_SLIPPERY.
8235 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8236 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8237 .deviceId(deviceA)
8238 .build());
8239 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceA)));
8240 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8241
8242 // Ensure that middle window can receive the remaining move events.
8243 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8244 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
8245 .deviceId(deviceB)
8246 .build());
8247 leftWindow->assertNoEvents();
8248 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
8249 rightWindow->assertNoEvents();
8250}
8251
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008252TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008253 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008254 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8255
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008256 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
8257 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008258 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008259 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008260
8261 sp<FakeWindowHandle> rightSpy =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008262 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy",
8263 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008264 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008265 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008266 rightSpy->setSpy(true);
8267 rightSpy->setTrustedOverlay(true);
8268
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008269 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
8270 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008271 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008272 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008273
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008274 mDispatcher->onWindowInfosChanged(
8275 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008276
8277 // Touch in the left window
8278 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8279 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8280 .build());
8281 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
8282 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008283 ASSERT_NO_FATAL_FAILURE(
8284 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008285
8286 // Touch another finger over the right windows
8287 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8288 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8289 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8290 .build());
8291 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
8292 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
8293 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
8294 mDispatcher->waitForIdle();
8295 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008296 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
8297 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008298
8299 // Release finger over left window. The UP actions are not treated as device interaction.
8300 // The windows that did not receive the UP pointer will receive MOVE events, but since this
8301 // is part of the UP action, we do not treat this as device interaction.
8302 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
8303 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8304 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8305 .build());
8306 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
8307 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8308 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8309 mDispatcher->waitForIdle();
8310 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8311
8312 // Move remaining finger
8313 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8314 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8315 .build());
8316 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8317 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8318 mDispatcher->waitForIdle();
8319 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008320 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008321
8322 // Release all fingers
8323 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8324 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8325 .build());
8326 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
8327 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
8328 mDispatcher->waitForIdle();
8329 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8330}
8331
8332TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
8333 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8334
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008335 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8336 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008337 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008338 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008339
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008340 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008341 setFocusedWindow(window);
8342 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
8343
8344 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008345 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008346 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008347 ASSERT_NO_FATAL_FAILURE(
8348 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008349
8350 // The UP actions are not treated as device interaction.
8351 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008352 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008353 mDispatcher->waitForIdle();
8354 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8355}
8356
Prabir Pradhan5893d362023-11-17 04:30:40 +00008357TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
8358 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8359
8360 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008361 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008362 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008363 sp<FakeWindowHandle> right =
8364 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
8365 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008366 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008367 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8368 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008369 spy->setFrame(Rect(0, 0, 200, 100));
8370 spy->setTrustedOverlay(true);
8371 spy->setSpy(true);
8372
8373 mDispatcher->onWindowInfosChanged(
8374 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
8375
8376 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008377 NotifyMotionArgs notifyArgs =
8378 generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8379 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008380 mDispatcher->notifyMotion(notifyArgs);
8381
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008382 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008383 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
8384 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008385 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008386 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8387 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008388 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008389 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8390
8391 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008392 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8393 ui::LogicalDisplayId::DEFAULT, {PointF{150, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008394 mDispatcher->notifyMotion(notifyArgs);
8395
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008396 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008397 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
8398 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008399 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008400 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8401 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008402 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008403 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8404
8405 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
8406}
8407
Linnan Liccf6ce32024-04-11 20:32:13 +08008408/**
8409 * When a device reports a DOWN event, which lands in a window that supports splits, and then the
8410 * device then reports a POINTER_DOWN, which lands in the location of a non-existing window, then
8411 * the previous window should receive this event and not be dropped.
8412 */
8413TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
8414 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008415 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8416 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008417 window->setFrame(Rect(0, 0, 100, 100));
8418 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8419
8420 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8421 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8422 .build());
8423
8424 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
8425
8426 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8427 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8428 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
8429 .build());
8430
8431 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_1_DOWN)));
8432}
8433
8434/**
8435 * When deviceA reports a DOWN event, which lands in a window that supports splits, and then deviceB
8436 * also reports a DOWN event, which lands in the location of a non-existing window, then the
8437 * previous window should receive deviceB's event and it should be dropped.
8438 */
8439TEST_F(InputDispatcherMultiDeviceTest, SecondDeviceDownEventDroppedWithoutWindowTarget) {
8440 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008441 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8442 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008443 window->setFrame(Rect(0, 0, 100, 100));
8444 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8445
8446 const DeviceId deviceA = 9;
8447 const DeviceId deviceB = 3;
8448
8449 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8450 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8451 .deviceId(deviceA)
8452 .build());
8453 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8454
8455 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8456 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
8457 .deviceId(deviceB)
8458 .build());
8459 window->assertNoEvents();
8460}
8461
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008462class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
8463protected:
8464 std::shared_ptr<FakeApplicationHandle> mApp;
8465 sp<FakeWindowHandle> mWindow;
8466
8467 virtual void SetUp() override {
8468 InputDispatcherTest::SetUp();
8469
8470 mApp = std::make_shared<FakeApplicationHandle>();
8471
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008472 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window",
8473 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008474 mWindow->setFrame(Rect(0, 0, 100, 100));
8475
8476 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8477 setFocusedWindow(mWindow);
8478 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
8479 }
8480
8481 void setFallback(int32_t keycode) {
8482 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
8483 return KeyEventBuilder(event).keyCode(keycode).build();
8484 });
8485 }
8486
8487 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008488 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
8489 ASSERT_NE(nullptr, event);
8490 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008491 }
8492};
8493
8494TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
8495 mDispatcher->notifyKey(
8496 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8497 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8498 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8499}
8500
8501TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
8502 mDispatcher->notifyKey(
8503 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8504 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8505 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8506}
8507
8508TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
8509 mDispatcher->notifyKey(
8510 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8511
8512 // Do not handle this key event.
8513 consumeKey(/*handled=*/false,
8514 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8515 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8516
8517 // Since the policy did not request any fallback to be generated, ensure there are no events.
8518 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8519}
8520
8521TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
8522 setFallback(AKEYCODE_B);
8523 mDispatcher->notifyKey(
8524 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8525
8526 // Do not handle this key event.
8527 consumeKey(/*handled=*/false,
8528 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8529
8530 // Since the key was not handled, ensure the fallback event was dispatched instead.
8531 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8532 consumeKey(/*handled=*/true,
8533 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8534 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8535
8536 // Release the original key, and ensure the fallback key is also released.
8537 mDispatcher->notifyKey(
8538 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8539 consumeKey(/*handled=*/false,
8540 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8541 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8542 consumeKey(/*handled=*/true,
8543 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8544 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8545
8546 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8547 mWindow->assertNoEvents();
8548}
8549
8550TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
8551 setFallback(AKEYCODE_B);
8552 mDispatcher->notifyKey(
8553 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8554
8555 // Do not handle this key event, but handle the fallback.
8556 consumeKey(/*handled=*/false,
8557 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8558 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8559 consumeKey(/*handled=*/true,
8560 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8561 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8562
8563 // Release the original key, and ensure the fallback key is also released.
8564 mDispatcher->notifyKey(
8565 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8566 // But this time, the app handles the original key.
8567 consumeKey(/*handled=*/true,
8568 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8569 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8570 // Ensure the fallback key is canceled.
8571 consumeKey(/*handled=*/true,
8572 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8573 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8574
8575 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8576 mWindow->assertNoEvents();
8577}
8578
8579TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
8580 setFallback(AKEYCODE_B);
8581 mDispatcher->notifyKey(
8582 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8583
8584 // Do not handle this key event.
8585 consumeKey(/*handled=*/false,
8586 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8587 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8588 // App does not handle the fallback either, so ensure another fallback is not generated.
8589 setFallback(AKEYCODE_C);
8590 consumeKey(/*handled=*/false,
8591 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8592 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8593
8594 // Release the original key, and ensure the fallback key is also released.
8595 setFallback(AKEYCODE_B);
8596 mDispatcher->notifyKey(
8597 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8598 consumeKey(/*handled=*/false,
8599 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8600 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8601 consumeKey(/*handled=*/false,
8602 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8603 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8604
8605 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8606 mWindow->assertNoEvents();
8607}
8608
8609TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
8610 setFallback(AKEYCODE_B);
8611 mDispatcher->notifyKey(
8612 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8613
8614 // Do not handle this key event, so fallback is generated.
8615 consumeKey(/*handled=*/false,
8616 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8617 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8618 consumeKey(/*handled=*/true,
8619 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8620 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8621
8622 // Release the original key, but assume the policy is misbehaving and it
8623 // generates an inconsistent fallback to the one from the DOWN event.
8624 setFallback(AKEYCODE_C);
8625 mDispatcher->notifyKey(
8626 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8627 consumeKey(/*handled=*/false,
8628 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8629 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8630 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
8631 consumeKey(/*handled=*/true,
8632 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8633 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8634
8635 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8636 mWindow->assertNoEvents();
8637}
8638
8639TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
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, so fallback is generated.
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 // The original key is canceled.
8653 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
8654 .keyCode(AKEYCODE_A)
8655 .addFlag(AKEY_EVENT_FLAG_CANCELED)
8656 .build());
8657 consumeKey(/*handled=*/false,
8658 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8659 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8660 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8661 // Ensure the fallback key is also canceled due to the original key being canceled.
8662 consumeKey(/*handled=*/true,
8663 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8664 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8665
8666 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8667 mWindow->assertNoEvents();
8668}
8669
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008670TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00008671 setFallback(AKEYCODE_B);
8672 mDispatcher->notifyKey(
8673 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8674
8675 // Do not handle this key event.
8676 consumeKey(/*handled=*/false,
8677 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8678 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8679 consumeKey(/*handled=*/true,
8680 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8681 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8682
8683 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8684 // When the unhandled key is reported to the policy next, remove the input channel.
8685 mDispatcher->removeInputChannel(mWindow->getToken());
8686 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8687 });
8688 // Release the original key, and let the app now handle the previously unhandled key.
8689 // This should result in the previously generated fallback key to be cancelled.
8690 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
8691 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
8692 // without holding the lock, because it need to synchronously fetch the fallback key. While in
8693 // the policy call, we will now remove the input channel. Once the policy call returns, the
8694 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
8695 // not cause any crashes.
8696 mDispatcher->notifyKey(
8697 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8698 consumeKey(/*handled=*/true,
8699 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8700 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8701}
8702
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008703TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
8704 setFallback(AKEYCODE_B);
8705 mDispatcher->notifyKey(
8706 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8707
8708 // Do not handle this key event.
8709 consumeKey(/*handled=*/false,
8710 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8711 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8712 consumeKey(/*handled=*/true,
8713 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8714 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8715
8716 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8717 // When the unhandled key is reported to the policy next, remove the window.
8718 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8719 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8720 });
8721 // Release the original key, which the app will not handle. When this unhandled key is reported
8722 // to the policy, the window will be removed.
8723 mDispatcher->notifyKey(
8724 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8725 consumeKey(/*handled=*/false,
8726 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8727 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8728
8729 // Since the window was removed, it loses focus, and the channel state will be reset.
8730 consumeKey(/*handled=*/true,
8731 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8732 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8733 mWindow->consumeFocusEvent(false);
8734 mWindow->assertNoEvents();
8735}
8736
8737TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
8738 setFallback(AKEYCODE_B);
8739 mDispatcher->notifyKey(
8740 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8741
8742 // Do not handle this key event.
8743 consumeKey(/*handled=*/false,
8744 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8745 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8746 const auto [seq, event] = mWindow->receiveEvent();
8747 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
8748 ASSERT_EQ(event->getType(), InputEventType::KEY);
8749 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
8750 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8751 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8752
8753 // Remove the window now, which should generate a cancellations and make the window lose focus.
8754 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8755 consumeKey(/*handled=*/true,
8756 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8757 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8758 consumeKey(/*handled=*/true,
8759 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8760 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8761 mWindow->consumeFocusEvent(false);
8762
8763 // Finish the event by reporting it as handled.
8764 mWindow->finishEvent(*seq);
8765 mWindow->assertNoEvents();
8766}
8767
Garfield Tan1c7bc862020-01-28 13:24:04 -08008768class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
8769protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08008770 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
8771 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008772
Chris Yea209fde2020-07-22 13:54:51 -07008773 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008774 sp<FakeWindowHandle> mWindow;
8775
8776 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00008777 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008778
Prabir Pradhandae52792023-12-15 07:36:40 +00008779 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008780 setUpWindow();
8781 }
8782
8783 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07008784 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008785 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window",
8786 ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008787
Vishnu Nair47074b82020-08-14 11:54:47 -07008788 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008789 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008790 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008791 mWindow->consumeFocusEvent(true);
8792 }
8793
Chris Ye2ad95392020-09-01 13:44:44 -07008794 void sendAndConsumeKeyDown(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008795 NotifyKeyArgs keyArgs =
8796 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008797 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008798 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008799 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008800
8801 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008802 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008803 }
8804
8805 void expectKeyRepeatOnce(int32_t repeatCount) {
8806 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008807 mWindow->consumeKeyEvent(
8808 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008809 }
8810
Chris Ye2ad95392020-09-01 13:44:44 -07008811 void sendAndConsumeKeyUp(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008812 NotifyKeyArgs keyArgs =
8813 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008814 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008815 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008816 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008817
8818 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008819 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008820 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008821 }
Hu Guofe3c8f12023-09-22 17:20:15 +08008822
8823 void injectKeyRepeat(int32_t repeatCount) {
8824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008825 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount,
8826 ui::LogicalDisplayId::DEFAULT))
Hu Guofe3c8f12023-09-22 17:20:15 +08008827 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8828 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08008829};
8830
8831TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00008832 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008833 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8834 expectKeyRepeatOnce(repeatCount);
8835 }
8836}
8837
8838TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00008839 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008840 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8841 expectKeyRepeatOnce(repeatCount);
8842 }
Harry Cutts33476232023-01-30 19:57:29 +00008843 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008844 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08008845 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8846 expectKeyRepeatOnce(repeatCount);
8847 }
8848}
8849
8850TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008851 sendAndConsumeKeyDown(/*deviceId=*/1);
8852 expectKeyRepeatOnce(/*repeatCount=*/1);
8853 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008854 mWindow->assertNoEvents();
8855}
8856
8857TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008858 sendAndConsumeKeyDown(/*deviceId=*/1);
8859 expectKeyRepeatOnce(/*repeatCount=*/1);
8860 sendAndConsumeKeyDown(/*deviceId=*/2);
8861 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008862 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00008863 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008864 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00008865 expectKeyRepeatOnce(/*repeatCount=*/2);
8866 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07008867 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00008868 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008869 mWindow->assertNoEvents();
8870}
8871
8872TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008873 sendAndConsumeKeyDown(/*deviceId=*/1);
8874 expectKeyRepeatOnce(/*repeatCount=*/1);
8875 sendAndConsumeKeyDown(/*deviceId=*/2);
8876 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008877 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00008878 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008879 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08008880 mWindow->assertNoEvents();
8881}
8882
liushenxiang42232912021-05-21 20:24:09 +08008883TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
8884 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00008885 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008886 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008887 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
liushenxiang42232912021-05-21 20:24:09 +08008888 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
8889 mWindow->assertNoEvents();
8890}
8891
Garfield Tan1c7bc862020-01-28 13:24:04 -08008892TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008893 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008894 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008895 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008896 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8897 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008898 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008899 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008900 }
8901}
8902
8903TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008904 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008905 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008906
8907 std::unordered_set<int32_t> idSet;
8908 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008909 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8910 ASSERT_NE(nullptr, repeatEvent);
8911 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008912 EXPECT_EQ(idSet.end(), idSet.find(id));
8913 idSet.insert(id);
8914 }
8915}
8916
Hu Guofe3c8f12023-09-22 17:20:15 +08008917TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
8918 injectKeyRepeat(0);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008919 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Hu Guofe3c8f12023-09-22 17:20:15 +08008920 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
8921 expectKeyRepeatOnce(repeatCount);
8922 }
8923 injectKeyRepeat(1);
8924 // Expect repeatCount to be 3 instead of 1
8925 expectKeyRepeatOnce(3);
8926}
8927
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008928/* Test InputDispatcher for MultiDisplay */
8929class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
8930public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008931 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008932 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08008933
Chris Yea209fde2020-07-22 13:54:51 -07008934 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008935 windowInPrimary = sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1",
8936 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008937
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008938 // Set focus window for primary display, but focused display would be second one.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008939 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07008940 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008941 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
8942
Vishnu Nair958da932020-08-21 17:12:37 -07008943 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008944 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08008945
Chris Yea209fde2020-07-22 13:54:51 -07008946 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008947 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008948 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008949 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008950 // Set focus display to second one.
8951 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +00008952 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
8953
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008954 // Set focus window for second display.
8955 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07008956 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008957 mDispatcher->onWindowInfosChanged(
8958 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008959 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008960 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008961 }
8962
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008963 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008964 InputDispatcherTest::TearDown();
8965
Chris Yea209fde2020-07-22 13:54:51 -07008966 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008967 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07008968 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008969 windowInSecondary.clear();
8970 }
8971
8972protected:
Chris Yea209fde2020-07-22 13:54:51 -07008973 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008974 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07008975 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008976 sp<FakeWindowHandle> windowInSecondary;
8977};
8978
8979TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
8980 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008982 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8983 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008984 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008985 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08008986 windowInSecondary->assertNoEvents();
8987
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008988 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008990 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008991 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08008992 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08008993 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08008994}
8995
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008996TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08008997 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008998 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008999 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009000 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009001 windowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08009002 windowInSecondary->assertNoEvents();
9003
9004 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009005 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009006 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08009007 windowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009008 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hungb92218b2018-08-14 12:00:21 +08009009
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009010 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009011 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08009012
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009013 // Old focus should receive a cancel event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009014 windowInSecondary->consumeKeyUp(ui::LogicalDisplayId::INVALID, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08009015
9016 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009017 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08009018 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009019 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08009020 windowInSecondary->assertNoEvents();
9021}
9022
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009023// Test per-display input monitors for motion event.
9024TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08009025 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009026 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08009027 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009028 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009029
9030 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009032 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9033 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009034 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009035 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9036 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009037 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009038 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009039
9040 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009041 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009042 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009043 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009044 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009045 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08009046 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08009047 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009048
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08009049 // Lift up the touch from the second display
9050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009051 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08009052 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9053 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
9054 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
9055
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009056 // Test inject a non-pointer motion event.
9057 // If specific a display, it will dispatch to the focused window of particular display,
9058 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009059 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009060 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL,
9061 ui::LogicalDisplayId::INVALID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009062 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009063 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009064 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009065 windowInSecondary->consumeMotionDown(ui::LogicalDisplayId::INVALID);
9066 monitorInSecondary.consumeMotionDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009067}
9068
9069// Test per-display input monitors for key event.
9070TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009071 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08009072 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009073 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08009074 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009075 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009076
9077 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009078 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009079 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009080 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009081 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009082 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
9083 monitorInSecondary.consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009084}
9085
Vishnu Nair958da932020-08-21 17:12:37 -07009086TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
9087 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009088 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2",
9089 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009090 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009091 mDispatcher->onWindowInfosChanged(
9092 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
9093 *windowInSecondary->getInfo()},
9094 {},
9095 0,
9096 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009097 setFocusedWindow(secondWindowInPrimary);
9098 windowInPrimary->consumeFocusEvent(false);
9099 secondWindowInPrimary->consumeFocusEvent(true);
9100
9101 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009102 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009103 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009104 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009105 windowInPrimary->assertNoEvents();
9106 windowInSecondary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009107 secondWindowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009108}
9109
Arthur Hungdfd528e2021-12-08 13:23:04 +00009110TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
9111 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009112 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009113 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009114 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009115
9116 // Test touch down on primary display.
9117 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009118 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9119 ui::LogicalDisplayId::DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009120 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009121 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9122 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009123
9124 // Test touch down on second display.
9125 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009126 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009127 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9128 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
9129 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
9130
9131 // Trigger cancel touch.
9132 mDispatcher->cancelCurrentTouch();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009133 windowInPrimary->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
9134 monitorInPrimary.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009135 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
9136 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
9137
9138 // Test inject a move motion event, no window/monitor should receive the event.
9139 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009140 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009141 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009142 << "Inject motion event should return InputEventInjectionResult::FAILED";
9143 windowInPrimary->assertNoEvents();
9144 monitorInPrimary.assertNoEvents();
9145
9146 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009147 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00009148 SECOND_DISPLAY_ID, {110, 200}))
9149 << "Inject motion event should return InputEventInjectionResult::FAILED";
9150 windowInSecondary->assertNoEvents();
9151 monitorInSecondary.assertNoEvents();
9152}
9153
Hu Guocb134f12023-12-23 13:42:44 +00009154/**
9155 * Send a key to the primary display and to the secondary display.
9156 * Then cause the key on the primary display to be canceled by sending in a stale key.
9157 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
9158 * does not get canceled.
9159 */
9160TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
9161 // Send a key down on primary display
9162 mDispatcher->notifyKey(
9163 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009164 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009165 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9166 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009167 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
9168 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00009169 windowInSecondary->assertNoEvents();
9170
9171 // Send a key down on second display
9172 mDispatcher->notifyKey(
9173 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9174 .displayId(SECOND_DISPLAY_ID)
9175 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9176 .build());
9177 windowInSecondary->consumeKeyEvent(
9178 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
9179 windowInPrimary->assertNoEvents();
9180
9181 // Send a valid key up event on primary display that will be dropped because it is stale
9182 NotifyKeyArgs staleKeyUp =
9183 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009184 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009185 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9186 .build();
9187 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
9188 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
9189 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
9190 mDispatcher->notifyKey(staleKeyUp);
9191
9192 // Only the key gesture corresponding to the dropped event should receive the cancel event.
9193 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
9194 // receive any events.
9195 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009196 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
Hu Guocb134f12023-12-23 13:42:44 +00009197 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
9198 windowInSecondary->assertNoEvents();
9199}
9200
9201/**
9202 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
9203 */
9204TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
9205 // Send touch down on primary display.
9206 mDispatcher->notifyMotion(
9207 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9208 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009209 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009210 .build());
9211 windowInPrimary->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009212 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00009213 windowInSecondary->assertNoEvents();
9214
9215 // Send touch down on second display.
9216 mDispatcher->notifyMotion(
9217 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9218 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9219 .displayId(SECOND_DISPLAY_ID)
9220 .build());
9221 windowInPrimary->assertNoEvents();
9222 windowInSecondary->consumeMotionEvent(
9223 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
9224
9225 // inject a valid MotionEvent on primary display that will be stale when it arrives.
9226 NotifyMotionArgs staleMotionUp =
9227 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009228 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009229 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9230 .build();
9231 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
9232 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
9233 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
9234 mDispatcher->notifyMotion(staleMotionUp);
9235
9236 // For stale motion events, we let the gesture to complete. This behaviour is different from key
9237 // events, where we would cancel the current keys instead.
9238 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
9239 windowInSecondary->assertNoEvents();
9240}
9241
Jackal Guof9696682018-10-05 12:23:23 +08009242class InputFilterTest : public InputDispatcherTest {
9243protected:
Linnan Li13bf76a2024-05-05 19:18:02 +08009244 void testNotifyMotion(ui::LogicalDisplayId displayId, bool expectToBeFiltered,
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009245 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08009246 NotifyMotionArgs motionArgs;
9247
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009248 motionArgs =
9249 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009250 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009251 motionArgs =
9252 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009253 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009254 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08009255 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009256 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009257 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08009258 } else {
9259 mFakePolicy->assertFilterInputEventWasNotCalled();
9260 }
9261 }
9262
9263 void testNotifyKey(bool expectToBeFiltered) {
9264 NotifyKeyArgs keyArgs;
9265
9266 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009267 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009268 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009269 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009270 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08009271
9272 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08009273 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009274 } else {
9275 mFakePolicy->assertFilterInputEventWasNotCalled();
9276 }
9277 }
9278};
9279
9280// Test InputFilter for MotionEvent
9281TEST_F(InputFilterTest, MotionEvent_InputFilter) {
9282 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009283 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009284 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009285
9286 // Enable InputFilter
9287 mDispatcher->setInputFilterEnabled(true);
9288 // Test touch on both primary and second display, and check if both events are filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009289 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009290 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009291
9292 // Disable InputFilter
9293 mDispatcher->setInputFilterEnabled(false);
9294 // Test touch on both primary and second display, and check if both events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009295 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009296 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009297}
9298
9299// Test InputFilter for KeyEvent
9300TEST_F(InputFilterTest, KeyEvent_InputFilter) {
9301 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009302 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009303
9304 // Enable InputFilter
9305 mDispatcher->setInputFilterEnabled(true);
9306 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009307 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009308
9309 // Disable InputFilter
9310 mDispatcher->setInputFilterEnabled(false);
9311 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009312 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009313}
9314
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009315// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
9316// logical display coordinate space.
9317TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
9318 ui::Transform firstDisplayTransform;
9319 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
9320 ui::Transform secondDisplayTransform;
9321 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
9322
9323 std::vector<gui::DisplayInfo> displayInfos(2);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009324 displayInfos[0].displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009325 displayInfos[0].transform = firstDisplayTransform;
9326 displayInfos[1].displayId = SECOND_DISPLAY_ID;
9327 displayInfos[1].transform = secondDisplayTransform;
9328
Patrick Williamsd828f302023-04-28 17:52:08 -05009329 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009330
9331 // Enable InputFilter
9332 mDispatcher->setInputFilterEnabled(true);
9333
9334 // Ensure the correct transforms are used for the displays.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009335 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true,
9336 firstDisplayTransform);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009337 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009338}
9339
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009340class InputFilterInjectionPolicyTest : public InputDispatcherTest {
9341protected:
9342 virtual void SetUp() override {
9343 InputDispatcherTest::SetUp();
9344
9345 /**
9346 * We don't need to enable input filter to test the injected event policy, but we enabled it
9347 * here to make the tests more realistic, since this policy only matters when inputfilter is
9348 * on.
9349 */
9350 mDispatcher->setInputFilterEnabled(true);
9351
9352 std::shared_ptr<InputApplicationHandle> application =
9353 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009354 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009355 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009356
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009357 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009358 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009359 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009360 setFocusedWindow(mWindow);
9361 mWindow->consumeFocusEvent(true);
9362 }
9363
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009364 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9365 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009366 KeyEvent event;
9367
9368 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9369 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009370 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
9371 AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009372 const int32_t additionalPolicyFlags =
9373 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
9374 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009375 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009376 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009377 policyFlags | additionalPolicyFlags));
9378
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009379 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009380 }
9381
9382 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9383 int32_t flags) {
9384 MotionEvent event;
9385 PointerProperties pointerProperties[1];
9386 PointerCoords pointerCoords[1];
9387 pointerProperties[0].clear();
9388 pointerProperties[0].id = 0;
9389 pointerCoords[0].clear();
9390 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
9391 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
9392
9393 ui::Transform identityTransform;
9394 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9395 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
9396 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
9397 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
9398 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07009399 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07009400 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00009401 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009402
9403 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
9404 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009405 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009406 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009407 policyFlags | additionalPolicyFlags));
9408
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009409 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009410 }
9411
9412private:
9413 sp<FakeWindowHandle> mWindow;
9414};
9415
9416TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009417 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
9418 // filter. Without it, the event will no different from a regularly injected event, and the
9419 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00009420 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
9421 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009422}
9423
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009424TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009425 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009426 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009427 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
9428}
9429
9430TEST_F(InputFilterInjectionPolicyTest,
9431 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
9432 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009433 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009434 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009435}
9436
9437TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00009438 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
9439 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009440}
9441
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009442class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
9443protected:
9444 virtual void SetUp() override {
9445 InputDispatcherTest::SetUp();
9446
9447 std::shared_ptr<FakeApplicationHandle> application =
9448 std::make_shared<FakeApplicationHandle>();
9449 application->setDispatchingTimeout(100ms);
9450 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009451 ui::LogicalDisplayId::DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00009452 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009453 mWindow->setDispatchingTimeout(100ms);
9454 mWindow->setFocusable(true);
9455
9456 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009457 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009458
9459 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
9460 setFocusedWindow(mWindow);
9461 mWindow->consumeFocusEvent(true);
9462 }
9463
Linnan Li13bf76a2024-05-05 19:18:02 +08009464 void notifyAndConsumeMotion(int32_t action, uint32_t source, ui::LogicalDisplayId displayId,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009465 nsecs_t eventTime) {
9466 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
9467 .displayId(displayId)
9468 .eventTime(eventTime)
9469 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9470 .build());
9471 mWindow->consumeMotionEvent(WithMotionAction(action));
9472 }
9473
9474private:
9475 sp<FakeWindowHandle> mWindow;
9476};
9477
9478TEST_F_WITH_FLAGS(
9479 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
9480 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9481 rate_limit_user_activity_poke_in_dispatcher))) {
9482 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
9483
9484 // First event of type TOUCH. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009485 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009486 milliseconds_to_nanoseconds(50));
9487 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009488 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
9489 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009490
9491 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009492 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009493 milliseconds_to_nanoseconds(130));
9494 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009495 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
9496 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009497
9498 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009499 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9500 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009501 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009502 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
9503 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009504
9505 // Within 50ns of previous TOUCH event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009506 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009507 milliseconds_to_nanoseconds(140));
9508 mFakePolicy->assertUserActivityNotPoked();
9509
9510 // Within 50ns of previous OTHER event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009511 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9512 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009513 mFakePolicy->assertUserActivityNotPoked();
9514
9515 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
9516 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009517 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009518 milliseconds_to_nanoseconds(160));
9519 mFakePolicy->assertUserActivityNotPoked();
9520
9521 // 65ns > 50ns has passed since previous OTHER event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009522 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9523 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009524 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009525 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
9526 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009527
9528 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009529 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009530 milliseconds_to_nanoseconds(300));
9531 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009532 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
9533 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009534
9535 // Assert that there's no more user activity poke event.
9536 mFakePolicy->assertUserActivityNotPoked();
9537}
9538
9539TEST_F_WITH_FLAGS(
9540 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
9541 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9542 rate_limit_user_activity_poke_in_dispatcher))) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009543 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009544 milliseconds_to_nanoseconds(200));
9545 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009546 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
9547 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009548
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009549 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009550 milliseconds_to_nanoseconds(280));
9551 mFakePolicy->assertUserActivityNotPoked();
9552
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009553 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009554 milliseconds_to_nanoseconds(340));
9555 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009556 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
9557 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009558}
9559
9560TEST_F_WITH_FLAGS(
9561 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
9562 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9563 rate_limit_user_activity_poke_in_dispatcher))) {
9564 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
9565
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009566 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9567 20);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009568 mFakePolicy->assertUserActivityPoked();
9569
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009570 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9571 30);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009572 mFakePolicy->assertUserActivityPoked();
9573}
9574
chaviwfd6d3512019-03-25 13:23:49 -07009575class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009576 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07009577 InputDispatcherTest::SetUp();
9578
Chris Yea209fde2020-07-22 13:54:51 -07009579 std::shared_ptr<FakeApplicationHandle> application =
9580 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009581 mUnfocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
9582 ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009583 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07009584
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009585 mFocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
9586 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009587 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07009588
9589 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009590 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07009591 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07009592
9593 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009594 mDispatcher->onWindowInfosChanged(
9595 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009596 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009597 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07009598 }
9599
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009600 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07009601 InputDispatcherTest::TearDown();
9602
9603 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009604 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07009605 }
9606
9607protected:
9608 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009609 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07009610 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07009611};
9612
9613// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9614// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
9615// the onPointerDownOutsideFocus callback.
9616TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009618 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9619 ui::LogicalDisplayId::DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009620 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009621 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009622
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009623 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07009624 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
9625}
9626
9627// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
9628// DOWN on the window that doesn't have focus. Ensure no window received the
9629// onPointerDownOutsideFocus callback.
9630TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009631 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009632 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009633 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009634 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009635 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009636
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009637 ASSERT_TRUE(mDispatcher->waitForIdle());
9638 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009639}
9640
9641// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
9642// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
9643TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08009644 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009645 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009646 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009647 mFocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009648
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009649 ASSERT_TRUE(mDispatcher->waitForIdle());
9650 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009651}
9652
9653// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9654// DOWN on the window that already has focus. Ensure no window received the
9655// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009656TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009658 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9659 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009660 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009661 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009662
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009663 ASSERT_TRUE(mDispatcher->waitForIdle());
9664 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009665}
9666
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009667// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
9668// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
9669TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
9670 const MotionEvent event =
9671 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
9672 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009673 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009674 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
9675 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009677 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009678 mUnfocusedWindow->consumeAnyMotionDown(ui::LogicalDisplayId::DEFAULT,
9679 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009680
9681 ASSERT_TRUE(mDispatcher->waitForIdle());
9682 mFakePolicy->assertOnPointerDownWasNotCalled();
9683 // Ensure that the unfocused window did not receive any FOCUS events.
9684 mUnfocusedWindow->assertNoEvents();
9685}
9686
chaviwaf87b3e2019-10-01 16:59:28 -07009687// These tests ensures we can send touch events to a single client when there are multiple input
9688// windows that point to the same client token.
9689class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
9690 virtual void SetUp() override {
9691 InputDispatcherTest::SetUp();
9692
Chris Yea209fde2020-07-22 13:54:51 -07009693 std::shared_ptr<FakeApplicationHandle> application =
9694 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009695 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009696 ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009697 mWindow1->setFrame(Rect(0, 0, 100, 100));
9698
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009699 mWindow2 = mWindow1->clone(ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009700 mWindow2->setFrame(Rect(100, 100, 200, 200));
9701
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009702 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009703 }
9704
9705protected:
9706 sp<FakeWindowHandle> mWindow1;
9707 sp<FakeWindowHandle> mWindow2;
9708
9709 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05009710 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07009711 vec2 vals = windowInfo->transform.transform(point.x, point.y);
9712 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07009713 }
9714
9715 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
9716 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009717 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009718 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009719 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009720 ASSERT_NE(nullptr, motionEvent);
9721 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07009722
9723 for (size_t i = 0; i < points.size(); i++) {
9724 float expectedX = points[i].x;
9725 float expectedY = points[i].y;
9726
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009727 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009728 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009729 << ", got " << motionEvent->getX(i);
9730 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009731 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009732 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07009733 }
9734 }
chaviw9eaa22c2020-07-01 16:21:27 -07009735
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009736 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
9737 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07009738 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009739 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009740 ui::LogicalDisplayId::DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07009741
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009742 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009743 }
chaviwaf87b3e2019-10-01 16:59:28 -07009744};
9745
9746TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
9747 // Touch Window 1
9748 PointF touchedPoint = {10, 10};
9749 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009750 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009751
9752 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009753 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009754
9755 // Touch Window 2
9756 touchedPoint = {150, 150};
9757 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009758 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009759}
9760
chaviw9eaa22c2020-07-01 16:21:27 -07009761TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
9762 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07009763 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009764 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009765
9766 // Touch Window 1
9767 PointF touchedPoint = {10, 10};
9768 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009769 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009770 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009771 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009772
9773 // Touch Window 2
9774 touchedPoint = {150, 150};
9775 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009776 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
9777 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009778
chaviw9eaa22c2020-07-01 16:21:27 -07009779 // Update the transform so rotation is set
9780 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009781 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009782 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009783 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009784}
9785
chaviw9eaa22c2020-07-01 16:21:27 -07009786TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009787 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009788 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009789
9790 // Touch Window 1
9791 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9792 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009793 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009794
9795 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009796 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
9797 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
9798 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07009799 touchedPoints.push_back(PointF{150, 150});
9800 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009801 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009802
chaviw9eaa22c2020-07-01 16:21:27 -07009803 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009804 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009805 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009806
chaviw9eaa22c2020-07-01 16:21:27 -07009807 // Update the transform so rotation is set for Window 2
9808 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009809 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009810 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009811 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009812}
9813
chaviw9eaa22c2020-07-01 16:21:27 -07009814TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009815 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009816 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009817
9818 // Touch Window 1
9819 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9820 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009821 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009822
9823 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009824 touchedPoints.push_back(PointF{150, 150});
9825 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009826
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009827 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009828
9829 // Move both windows
9830 touchedPoints = {{20, 20}, {175, 175}};
9831 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9832 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9833
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009834 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009835
chaviw9eaa22c2020-07-01 16:21:27 -07009836 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009837 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009838 expectedPoints.pop_back();
9839
9840 // Touch Window 2
9841 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009842 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009843 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009844 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009845
9846 // Move both windows
9847 touchedPoints = {{20, 20}, {175, 175}};
9848 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9849 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9850
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009851 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009852}
9853
9854TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
9855 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009856 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009857
9858 // Touch Window 1
9859 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9860 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009861 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009862
9863 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009864 touchedPoints.push_back(PointF{150, 150});
9865 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009866
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009867 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009868
9869 // Move both windows
9870 touchedPoints = {{20, 20}, {175, 175}};
9871 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9872 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9873
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009874 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009875}
9876
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009877/**
9878 * When one of the windows is slippery, the touch should not slip into the other window with the
9879 * same input channel.
9880 */
9881TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
9882 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009883 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009884
9885 // Touch down in window 1
9886 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009887 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009888 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
9889
9890 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
9891 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
9892 // getting generated.
9893 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009894 ui::LogicalDisplayId::DEFAULT, {{150, 150}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009895
9896 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
9897}
9898
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009899/**
9900 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
9901 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
9902 * that the pointer is hovering over may have a different transform.
9903 */
9904TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009905 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009906
9907 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009908 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
9909 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9910 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009911 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
9912 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009913 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009914 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9915 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9916 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009917 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009918 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009919 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
9920}
9921
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009922class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
9923 virtual void SetUp() override {
9924 InputDispatcherTest::SetUp();
9925
Chris Yea209fde2020-07-22 13:54:51 -07009926 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009927 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009928 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009929 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009930 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009931 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07009932 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009933
9934 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009935 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009936
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009937 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009938 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009939 mWindow->consumeFocusEvent(true);
9940 }
9941
9942 virtual void TearDown() override {
9943 InputDispatcherTest::TearDown();
9944 mWindow.clear();
9945 }
9946
9947protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009948 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07009949 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009950 sp<FakeWindowHandle> mWindow;
9951 static constexpr PointF WINDOW_LOCATION = {20, 20};
9952
9953 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009954 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
9955 .x(WINDOW_LOCATION.x)
9956 .y(WINDOW_LOCATION.y);
9957 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9958 .pointer(touchingPointer)
9959 .build());
9960 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9961 .pointer(touchingPointer)
9962 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009963 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009964
9965 sp<FakeWindowHandle> addSpyWindow() {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009966 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy",
9967 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009968 spy->setTrustedOverlay(true);
9969 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009970 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009971 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009972 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009973 return spy;
9974 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009975};
9976
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009977// Send a tap and respond, which should not cause an ANR.
9978TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
9979 tapOnWindow();
9980 mWindow->consumeMotionDown();
9981 mWindow->consumeMotionUp();
9982 ASSERT_TRUE(mDispatcher->waitForIdle());
9983 mFakePolicy->assertNotifyAnrWasNotCalled();
9984}
9985
9986// Send a regular key and respond, which should not cause an ANR.
9987TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009989 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009990 ASSERT_TRUE(mDispatcher->waitForIdle());
9991 mFakePolicy->assertNotifyAnrWasNotCalled();
9992}
9993
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009994TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
9995 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009996 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009997 mWindow->consumeFocusEvent(false);
9998
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009999 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010000 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10001 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
10002 CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +000010003 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010004 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010005 // Key will not go to window because we have no focused window.
10006 // The 'no focused window' ANR timer should start instead.
10007
10008 // Now, the focused application goes away.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010009 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, nullptr);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010010 // The key should get dropped and there should be no ANR.
10011
10012 ASSERT_TRUE(mDispatcher->waitForIdle());
10013 mFakePolicy->assertNotifyAnrWasNotCalled();
10014}
10015
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010016// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010017// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10018// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010019TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010020 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010021 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10022 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010023
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010024 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010025 ASSERT_TRUE(sequenceNum);
10026 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010027 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010028
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010029 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010030 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010031 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010032 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010033 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010034}
10035
10036// Send a key to the app and have the app not respond right away.
10037TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
10038 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010040 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010041 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010042 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010043 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010044 ASSERT_TRUE(mDispatcher->waitForIdle());
10045}
10046
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010047// We have a focused application, but no focused window
10048TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -070010049 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010050 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010051 mWindow->consumeFocusEvent(false);
10052
10053 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010055 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10056 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010057 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10058 mDispatcher->waitForIdle();
10059 mFakePolicy->assertNotifyAnrWasNotCalled();
10060
10061 // Once a focused event arrives, we get an ANR for this application
10062 // We specify the injection timeout to be smaller than the application timeout, to ensure that
10063 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010064 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010065 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10066 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT, 50ms,
Linnan Li13bf76a2024-05-05 19:18:02 +080010067 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010068 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010069 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -070010070 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010071 ASSERT_TRUE(mDispatcher->waitForIdle());
10072}
10073
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010074/**
10075 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
10076 * there will not be an ANR.
10077 */
10078TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
10079 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010080 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010081 mWindow->consumeFocusEvent(false);
10082
10083 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -070010084 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
10085 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010086 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
10087 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
10088
10089 // Define a valid key down event that is stale (too old).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010090 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
10091 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN,
10092 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime,
10093 eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010094
Hu Guofe3c8f12023-09-22 17:20:15 +080010095 const int32_t policyFlags =
10096 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010097
10098 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +000010099 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010100 InputEventInjectionSync::WAIT_FOR_RESULT,
10101 INJECT_EVENT_TIMEOUT, policyFlags);
10102 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
10103 << "Injection should fail because the event is stale";
10104
10105 ASSERT_TRUE(mDispatcher->waitForIdle());
10106 mFakePolicy->assertNotifyAnrWasNotCalled();
10107 mWindow->assertNoEvents();
10108}
10109
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010110// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010111// Make sure that we don't notify policy twice about the same ANR.
10112TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010113 const std::chrono::duration appTimeout = 400ms;
10114 mApplication->setDispatchingTimeout(appTimeout);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010115 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010116
Vishnu Nair47074b82020-08-14 11:54:47 -070010117 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010118 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010119 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010120
10121 // Once a focused event arrives, we get an ANR for this application
10122 // We specify the injection timeout to be smaller than the application timeout, to ensure that
10123 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010124 const std::chrono::duration eventInjectionTimeout = 100ms;
10125 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010126 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010127 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10128 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT,
10129 eventInjectionTimeout,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010130 /*allowKeyRepeat=*/false);
10131 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
10132 << "result=" << ftl::enum_string(result);
10133 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
10134 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
10135 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
10136 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010137
Vishnu Naire4df8752022-09-08 09:17:55 -070010138 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010139 // ANR should not be raised again. It is up to policy to do that if it desires.
10140 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010141
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010142 // If we now get a focused window, the ANR should stop, but the policy handles that via
10143 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010144 ASSERT_TRUE(mDispatcher->waitForIdle());
10145}
10146
10147// We have a focused application, but no focused window
10148TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -070010149 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010150 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010151 mWindow->consumeFocusEvent(false);
10152
10153 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010154 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010155
Vishnu Naire4df8752022-09-08 09:17:55 -070010156 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10157 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010158
10159 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010160 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010161 ASSERT_TRUE(mDispatcher->waitForIdle());
10162 mWindow->assertNoEvents();
10163}
10164
10165/**
10166 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
10167 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
10168 * If we process 1 of the events, but ANR on the second event with the same timestamp,
10169 * the ANR mechanism should still work.
10170 *
10171 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
10172 * DOWN event, while not responding on the second one.
10173 */
10174TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
10175 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010176 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010177 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010178 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10179 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010180 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010181
10182 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010183 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010184 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010185 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10186 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010187 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010188
10189 // 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 -070010190 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010191 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010192 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010193}
10194
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010195// A spy window can receive an ANR
10196TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
10197 sp<FakeWindowHandle> spy = addSpyWindow();
10198
10199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010200 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10201 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010202 mWindow->consumeMotionDown();
10203
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010204 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010205 ASSERT_TRUE(sequenceNum);
10206 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010207 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010208
10209 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010210 spy->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010211 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010212 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010213 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010214}
10215
10216// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010217// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010218TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
10219 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010220
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010222 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
10223 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
10224 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10225 injectKeyUp(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010226
10227 // Stuck on the ACTION_UP
10228 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010229 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010230
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010231 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010232 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010233 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10234 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010235
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010236 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010237 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010238 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010239 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010240 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010241}
10242
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010243// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010244// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010245TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
10246 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010247
10248 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010249 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10250 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010251
10252 mWindow->consumeMotionDown();
10253 // Stuck on the ACTION_UP
10254 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010255 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010256
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010257 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010258 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010259 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10260 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010261
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010262 mWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010263 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010264 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010265 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010266 spy->assertNoEvents();
10267}
10268
10269TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010270 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010271
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010272 FakeMonitorReceiver monitor =
10273 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010274
10275 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010276 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10277 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010278
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010279 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010280 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
10281 ASSERT_TRUE(consumeSeq);
10282
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010283 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
10284 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010285
10286 monitor.finishEvent(*consumeSeq);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010287 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010288
10289 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010290 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010291}
10292
10293// If a window is unresponsive, then you get anr. if the window later catches up and starts to
10294// process events, you don't get an anr. When the window later becomes unresponsive again, you
10295// get an ANR again.
10296// 1. tap -> block on ACTION_UP -> receive ANR
10297// 2. consume all pending events (= queue becomes healthy again)
10298// 3. tap again -> block on ACTION_UP again -> receive ANR second time
10299TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
10300 tapOnWindow();
10301
10302 mWindow->consumeMotionDown();
10303 // Block on ACTION_UP
10304 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010305 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010306 mWindow->consumeMotionUp(); // Now the connection should be healthy again
10307 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010308 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010309 mWindow->assertNoEvents();
10310
10311 tapOnWindow();
10312 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010313 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010314 mWindow->consumeMotionUp();
10315
10316 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010317 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010318 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010319 mWindow->assertNoEvents();
10320}
10321
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010322// If a connection remains unresponsive for a while, make sure policy is only notified once about
10323// it.
10324TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010326 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10327 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010328
10329 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010330 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010331 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010332 // 'notifyConnectionUnresponsive' should only be called once per connection
10333 mFakePolicy->assertNotifyAnrWasNotCalled();
10334 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010335 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010336 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010337 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010338 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010339 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010340 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010341 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010342}
10343
10344/**
10345 * 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 -070010346 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010347 */
10348TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010349 // The timeouts in this test are established by relying on the fact that the "key waiting for
10350 // events timeout" is equal to 500ms.
10351 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010352 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010353 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010354
10355 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010356 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010357 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010358 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010359 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010360
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010361 // Don't finish the events yet, and send a key
10362 mDispatcher->notifyKey(
10363 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10364 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10365 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010366 // Key will not be sent to the window, yet, because the window is still processing events
10367 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010368 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010369 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010370
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010371 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010372 // if we wait long enough though, dispatcher will give up, and still send the key
10373 // to the focused window, even though we have not yet finished the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010374 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010375 mWindow->finishEvent(*downSequenceNum);
10376 mWindow->finishEvent(*upSequenceNum);
10377}
10378
10379/**
10380 * If a window is processing a motion event, and then a key event comes in, the key event should
10381 * not go to the focused window until the motion is processed.
10382 * If then a new motion comes in, then the pending key event should be going to the currently
10383 * focused window right away.
10384 */
10385TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010386 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
10387 // The timeouts in this test are established by relying on the fact that the "key waiting for
10388 // events timeout" is equal to 500ms.
10389 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010390 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010391 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010392
10393 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010394 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010395 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010396 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010397 ASSERT_TRUE(upSequenceNum);
10398 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010399 mDispatcher->notifyKey(
10400 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10401 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10402 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010403 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010404 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010405
10406 // Now tap down again. It should cause the pending key to go to the focused window right away.
10407 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010408 // Now that we tapped, we should receive the key immediately.
10409 // Since there's still room for slowness, we use 200ms, which is much less than
10410 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
10411 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
10412 ASSERT_NE(nullptr, keyEvent);
10413 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
10414 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
10415 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
10416 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010417 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
10418 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010419 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10420 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010421 mWindow->assertNoEvents();
10422}
10423
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010424/**
10425 * Send an event to the app and have the app not respond right away.
10426 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10427 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
10428 * At some point, the window becomes responsive again.
10429 * Ensure that subsequent events get dropped, and the next gesture is delivered.
10430 */
10431TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
10432 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10433 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
10434 .build());
10435
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010436 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010437 ASSERT_TRUE(sequenceNum);
10438 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10439 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10440
10441 mWindow->finishEvent(*sequenceNum);
10442 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
10443 ASSERT_TRUE(mDispatcher->waitForIdle());
10444 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10445
10446 // Now that the window is responsive, let's continue the gesture.
10447 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10448 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10449 .build());
10450
10451 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10452 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10453 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10454 .build());
10455
10456 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10457 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10458 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10459 .build());
10460 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10461 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10462 .build());
10463 // We already canceled this pointer, so the window shouldn't get any new events.
10464 mWindow->assertNoEvents();
10465
10466 // Start another one.
10467 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10468 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
10469 .build());
10470 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10471}
10472
Prabir Pradhanfc364722024-02-08 17:51:20 +000010473// Send an event to the app and have the app not respond right away. Then remove the app window.
10474// When the window is removed, the dispatcher will cancel the events for that window.
10475// So InputDispatcher will enqueue ACTION_CANCEL event as well.
10476TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
10477 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010478 AINPUT_SOURCE_TOUCHSCREEN,
10479 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010480
10481 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10482 ASSERT_TRUE(sequenceNum);
10483
10484 // Remove the window, but the input channel should remain alive.
10485 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10486
10487 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10488 // Since the window was removed, Dispatcher does not know the PID associated with the window
10489 // anymore, so the policy is notified without the PID.
10490 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
10491 /*pid=*/std::nullopt);
10492
10493 mWindow->finishEvent(*sequenceNum);
10494 // The cancellation was generated when the window was removed, along with the focus event.
10495 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010496 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010497 mWindow->consumeFocusEvent(false);
10498 ASSERT_TRUE(mDispatcher->waitForIdle());
10499 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10500}
10501
10502// Send an event to the app and have the app not respond right away. Wait for the policy to be
10503// notified of the unresponsive window, then remove the app window.
10504TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
10505 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010506 AINPUT_SOURCE_TOUCHSCREEN,
10507 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010508
10509 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10510 ASSERT_TRUE(sequenceNum);
10511 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10512 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10513
10514 // Remove the window, but the input channel should remain alive.
10515 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10516
10517 mWindow->finishEvent(*sequenceNum);
10518 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
10519 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010520 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010521 mWindow->consumeFocusEvent(false);
10522 ASSERT_TRUE(mDispatcher->waitForIdle());
10523 // Since the window was removed, Dispatcher does not know the PID associated with the window
10524 // becoming responsive, so the policy is notified without the PID.
10525 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10526}
10527
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010528class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
10529 virtual void SetUp() override {
10530 InputDispatcherTest::SetUp();
10531
Chris Yea209fde2020-07-22 13:54:51 -070010532 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010533 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010534 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010535 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010536 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010537 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010538 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010539
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010540 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010541 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010542 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010543 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010544
10545 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010546 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -070010547 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010548
10549 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010550 mDispatcher->onWindowInfosChanged(
10551 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010552 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010553 mFocusedWindow->consumeFocusEvent(true);
10554 }
10555
10556 virtual void TearDown() override {
10557 InputDispatcherTest::TearDown();
10558
10559 mUnfocusedWindow.clear();
10560 mFocusedWindow.clear();
10561 }
10562
10563protected:
Chris Yea209fde2020-07-22 13:54:51 -070010564 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010565 sp<FakeWindowHandle> mUnfocusedWindow;
10566 sp<FakeWindowHandle> mFocusedWindow;
10567 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
10568 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
10569 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
10570
10571 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
10572
10573 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
10574
10575private:
10576 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010577 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010578 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10579 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010580 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010581 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10582 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010583 }
10584};
10585
10586// If we have 2 windows that are both unresponsive, the one with the shortest timeout
10587// should be ANR'd first.
10588TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010589 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010590 injectMotionEvent(*mDispatcher,
10591 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10592 AINPUT_SOURCE_TOUCHSCREEN)
10593 .pointer(PointerBuilder(0, ToolType::FINGER)
10594 .x(FOCUSED_WINDOW_LOCATION.x)
10595 .y(FOCUSED_WINDOW_LOCATION.y))
10596 .build()));
10597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10598 injectMotionEvent(*mDispatcher,
10599 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
10600 AINPUT_SOURCE_TOUCHSCREEN)
10601 .pointer(PointerBuilder(0, ToolType::FINGER)
10602 .x(FOCUSED_WINDOW_LOCATION.x)
10603 .y(FOCUSED_WINDOW_LOCATION.y))
10604 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010605 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010606 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010607 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010608 // We consumed all events, so no ANR
10609 ASSERT_TRUE(mDispatcher->waitForIdle());
10610 mFakePolicy->assertNotifyAnrWasNotCalled();
10611
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010612 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010613 injectMotionEvent(*mDispatcher,
10614 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10615 AINPUT_SOURCE_TOUCHSCREEN)
10616 .pointer(PointerBuilder(0, ToolType::FINGER)
10617 .x(FOCUSED_WINDOW_LOCATION.x)
10618 .y(FOCUSED_WINDOW_LOCATION.y))
10619 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010620 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010621 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010622
10623 const std::chrono::duration timeout =
10624 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010625 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010626
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010627 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010628 mFocusedWindow->consumeMotionDown();
10629 // This cancel is generated because the connection was unresponsive
10630 mFocusedWindow->consumeMotionCancel();
10631 mFocusedWindow->assertNoEvents();
10632 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010633 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010634 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10635 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010636 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010637}
10638
10639// If we have 2 windows with identical timeouts that are both unresponsive,
10640// it doesn't matter which order they should have ANR.
10641// But we should receive ANR for both.
10642TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
10643 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010644 mUnfocusedWindow->setDispatchingTimeout(
10645 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010646 mDispatcher->onWindowInfosChanged(
10647 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010648
10649 tapOnFocusedWindow();
10650 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010651 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010652 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
10653 mFocusedWindow->getDispatchingTimeout(
10654 DISPATCHING_TIMEOUT)),
10655 mFakePolicy->getUnresponsiveWindowToken(0ms)};
10656
10657 ASSERT_THAT(anrConnectionTokens,
10658 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10659 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010660
10661 ASSERT_TRUE(mDispatcher->waitForIdle());
10662 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010663
10664 mFocusedWindow->consumeMotionDown();
10665 mFocusedWindow->consumeMotionUp();
10666 mUnfocusedWindow->consumeMotionOutside();
10667
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010668 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
10669 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010670
10671 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010672 ASSERT_THAT(responsiveTokens,
10673 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10674 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010675 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010676}
10677
10678// If a window is already not responding, the second tap on the same window should be ignored.
10679// We should also log an error to account for the dropped event (not tested here).
10680// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
10681TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
10682 tapOnFocusedWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010683 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010684 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010685 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010686 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010687 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010688 ASSERT_TRUE(upEventSequenceNum);
10689 const std::chrono::duration timeout =
10690 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010691 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010692
10693 // Tap once again
10694 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010695 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010696 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10697 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010698 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010699 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010700 FOCUSED_WINDOW_LOCATION));
10701 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
10702 // valid touch target
10703 mUnfocusedWindow->assertNoEvents();
10704
10705 // Consume the first tap
10706 mFocusedWindow->finishEvent(*downEventSequenceNum);
10707 mFocusedWindow->finishEvent(*upEventSequenceNum);
10708 ASSERT_TRUE(mDispatcher->waitForIdle());
10709 // The second tap did not go to the focused window
10710 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010711 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -080010712 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10713 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010714 mFakePolicy->assertNotifyAnrWasNotCalled();
10715}
10716
10717// If you tap outside of all windows, there will not be ANR
10718TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010719 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010720 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10721 ui::LogicalDisplayId::DEFAULT, LOCATION_OUTSIDE_ALL_WINDOWS));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010722 ASSERT_TRUE(mDispatcher->waitForIdle());
10723 mFakePolicy->assertNotifyAnrWasNotCalled();
10724}
10725
10726// Since the focused window is paused, tapping on it should not produce any events
10727TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
10728 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010729 mDispatcher->onWindowInfosChanged(
10730 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010731
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010732 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010733 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10734 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010735
10736 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
10737 ASSERT_TRUE(mDispatcher->waitForIdle());
10738 // Should not ANR because the window is paused, and touches shouldn't go to it
10739 mFakePolicy->assertNotifyAnrWasNotCalled();
10740
10741 mFocusedWindow->assertNoEvents();
10742 mUnfocusedWindow->assertNoEvents();
10743}
10744
10745/**
10746 * 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 -070010747 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010748 * If a different window becomes focused at this time, the key should go to that window instead.
10749 *
10750 * Warning!!!
10751 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
10752 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010753 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010754 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
10755 *
10756 * If that value changes, this test should also change.
10757 */
10758TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
10759 // Set a long ANR timeout to prevent it from triggering
10760 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010761 mDispatcher->onWindowInfosChanged(
10762 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010763
10764 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010765 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010766 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010767 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010768 ASSERT_TRUE(upSequenceNum);
10769 // Don't finish the events yet, and send a key
10770 // Injection will succeed because we will eventually give up and send the key to the focused
10771 // window even if motions are still being processed.
10772
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010773 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010774 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10775 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010776 /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010778 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010779 // and the key remains pending, waiting for the touch events to be processed.
10780 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
10781 // under the hood.
10782 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
10783 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010784
10785 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -070010786 mFocusedWindow->setFocusable(false);
10787 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010788 mDispatcher->onWindowInfosChanged(
10789 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010790 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010791
10792 // Focus events should precede the key events
10793 mUnfocusedWindow->consumeFocusEvent(true);
10794 mFocusedWindow->consumeFocusEvent(false);
10795
10796 // Finish the tap events, which should unblock dispatcher
10797 mUnfocusedWindow->finishEvent(*downSequenceNum);
10798 mUnfocusedWindow->finishEvent(*upSequenceNum);
10799
10800 // Now that all queues are cleared and no backlog in the connections, the key event
10801 // can finally go to the newly focused "mUnfocusedWindow".
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010802 mUnfocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010803 mFocusedWindow->assertNoEvents();
10804 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010805 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010806}
10807
10808// When the touch stream is split across 2 windows, and one of them does not respond,
10809// then ANR should be raised and the touch should be canceled for the unresponsive window.
10810// The other window should not be affected by that.
10811TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
10812 // Touch Window 1
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010813 mDispatcher->notifyMotion(
10814 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10815 ui::LogicalDisplayId::DEFAULT, {FOCUSED_WINDOW_LOCATION}));
10816 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010817
10818 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +000010819 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010820 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10821 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010822 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010823
10824 const std::chrono::duration timeout =
10825 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010826 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010827
10828 mUnfocusedWindow->consumeMotionDown();
10829 mFocusedWindow->consumeMotionDown();
10830 // Focused window may or may not receive ACTION_MOVE
10831 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010832 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010833 ASSERT_TRUE(moveOrCancelSequenceNum);
10834 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
10835 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -070010836 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010837 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
10838 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
10839 mFocusedWindow->consumeMotionCancel();
10840 } else {
10841 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
10842 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010843 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010844 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10845 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010846
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010847 mUnfocusedWindow->assertNoEvents();
10848 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010849 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010850}
10851
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010852/**
10853 * If we have no focused window, and a key comes in, we start the ANR timer.
10854 * The focused application should add a focused window before the timer runs out to prevent ANR.
10855 *
10856 * If the user touches another application during this time, the key should be dropped.
10857 * Next, if a new focused window comes in, without toggling the focused application,
10858 * then no ANR should occur.
10859 *
10860 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
10861 * but in some cases the policy may not update the focused application.
10862 */
10863TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
10864 std::shared_ptr<FakeApplicationHandle> focusedApplication =
10865 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -070010866 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010867 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, focusedApplication);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010868 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
10869 mFocusedWindow->setFocusable(false);
10870
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010871 mDispatcher->onWindowInfosChanged(
10872 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010873 mFocusedWindow->consumeFocusEvent(false);
10874
10875 // Send a key. The ANR timer should start because there is no focused window.
10876 // 'focusedApplication' will get blamed if this timer completes.
10877 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010878 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010879 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10880 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010881 /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +000010882 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010883 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010884
10885 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
10886 // then the injected touches won't cause the focused event to get dropped.
10887 // The dispatcher only checks for whether the queue should be pruned upon queueing.
10888 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
10889 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
10890 // For this test, it means that the key would get delivered to the window once it becomes
10891 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010892 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010893
10894 // Touch unfocused window. This should force the pending key to get dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010895 mDispatcher->notifyMotion(
10896 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10897 ui::LogicalDisplayId::DEFAULT, {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010898
10899 // We do not consume the motion right away, because that would require dispatcher to first
10900 // process (== drop) the key event, and by that time, ANR will be raised.
10901 // Set the focused window first.
10902 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010903 mDispatcher->onWindowInfosChanged(
10904 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010905 setFocusedWindow(mFocusedWindow);
10906 mFocusedWindow->consumeFocusEvent(true);
10907 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
10908 // to another application. This could be a bug / behaviour in the policy.
10909
10910 mUnfocusedWindow->consumeMotionDown();
10911
10912 ASSERT_TRUE(mDispatcher->waitForIdle());
10913 // Should not ANR because we actually have a focused window. It was just added too slowly.
10914 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
10915}
10916
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010917/**
10918 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
10919 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
10920 * dispatcher doesn't prune pointer events incorrectly.
10921 *
10922 * This test reproduces a crash in InputDispatcher.
10923 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
10924 *
10925 * Keep the currently focused application (mApplication), and have no focused window.
10926 * We set up two additional windows:
10927 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
10928 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
10929 * window. This window is not focusable, but is touchable.
10930 *
10931 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
10932 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
10933 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
10934 *
10935 * Now, we touch "Another window". This window is owned by a different application than
10936 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
10937 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
10938 * dropping the events from its queue. Ensure that no crash occurs.
10939 *
10940 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
10941 * This does not affect the test running time.
10942 */
10943TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
10944 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
10945 std::make_shared<FakeApplicationHandle>();
10946 systemUiApplication->setDispatchingTimeout(3000ms);
10947 mFakePolicy->setStaleEventTimeout(3000ms);
10948 sp<FakeWindowHandle> navigationBar =
10949 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010950 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010951 navigationBar->setFocusable(false);
10952 navigationBar->setWatchOutsideTouch(true);
10953 navigationBar->setFrame(Rect(0, 0, 100, 100));
10954
10955 mApplication->setDispatchingTimeout(3000ms);
10956 // 'mApplication' is already focused, but we call it again here to make it explicit.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010957 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010958
10959 std::shared_ptr<FakeApplicationHandle> anotherApplication =
10960 std::make_shared<FakeApplicationHandle>();
10961 sp<FakeWindowHandle> appWindow =
10962 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010963 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010964 appWindow->setFocusable(false);
10965 appWindow->setFrame(Rect(100, 100, 200, 200));
10966
10967 mDispatcher->onWindowInfosChanged(
10968 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
10969 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
10970 mFocusedWindow->consumeFocusEvent(false);
10971
10972 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
10973 // in response.
10974 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10975 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10976 .build());
10977 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10978
10979 // Key will not be sent anywhere because we have no focused window. It will remain pending.
10980 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
10981 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010982 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10983 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010984 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010985 /*allowKeyRepeat=*/false);
10986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10987
10988 // Finish the gesture - lift up finger and inject ACTION_UP key event
10989 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10990 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10991 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010992 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0,
10993 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010994 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010995 /*allowKeyRepeat=*/false);
10996 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10997 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
10998 // getting any events yet.
10999 navigationBar->assertNoEvents();
11000
11001 // Now touch "Another window". This touch is going to a different application than the one we
11002 // are waiting for (which is 'mApplication').
11003 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
11004 // trying to be injected) and to continue processing the rest of the events in the original
11005 // order.
11006 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11007 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
11008 .build());
11009 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
11010 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
11011 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
11012
11013 appWindow->assertNoEvents();
11014 navigationBar->assertNoEvents();
11015}
11016
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011017// These tests ensure we cannot send touch events to a window that's positioned behind a window
11018// that has feature NO_INPUT_CHANNEL.
11019// Layout:
11020// Top (closest to user)
11021// mNoInputWindow (above all windows)
11022// mBottomWindow
11023// Bottom (furthest from user)
11024class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
11025 virtual void SetUp() override {
11026 InputDispatcherTest::SetUp();
11027
11028 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011029 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
11030 "Window without input channel",
11031 ui::LogicalDisplayId::DEFAULT,
11032 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011033 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011034 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
11035 // It's perfectly valid for this window to not have an associated input channel
11036
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011037 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011038 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011039 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
11040
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011041 mDispatcher->onWindowInfosChanged(
11042 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011043 }
11044
11045protected:
11046 std::shared_ptr<FakeApplicationHandle> mApplication;
11047 sp<FakeWindowHandle> mNoInputWindow;
11048 sp<FakeWindowHandle> mBottomWindow;
11049};
11050
11051TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
11052 PointF touchedPoint = {10, 10};
11053
Prabir Pradhan678438e2023-04-13 19:32:51 +000011054 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011055 AINPUT_SOURCE_TOUCHSCREEN,
11056 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011057
11058 mNoInputWindow->assertNoEvents();
11059 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
11060 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
11061 // and therefore should prevent mBottomWindow from receiving touches
11062 mBottomWindow->assertNoEvents();
11063}
11064
11065/**
11066 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
11067 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
11068 */
11069TEST_F(InputDispatcherMultiWindowOcclusionTests,
11070 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011071 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
11072 "Window with input channel and NO_INPUT_CHANNEL",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011073 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011074
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011075 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011076 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011077 mDispatcher->onWindowInfosChanged(
11078 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011079
11080 PointF touchedPoint = {10, 10};
11081
Prabir Pradhan678438e2023-04-13 19:32:51 +000011082 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011083 AINPUT_SOURCE_TOUCHSCREEN,
11084 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011085
11086 mNoInputWindow->assertNoEvents();
11087 mBottomWindow->assertNoEvents();
11088}
11089
Vishnu Nair958da932020-08-21 17:12:37 -070011090class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
11091protected:
11092 std::shared_ptr<FakeApplicationHandle> mApp;
11093 sp<FakeWindowHandle> mWindow;
11094 sp<FakeWindowHandle> mMirror;
11095
11096 virtual void SetUp() override {
11097 InputDispatcherTest::SetUp();
11098 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011099 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11100 ui::LogicalDisplayId::DEFAULT);
11101 mMirror = mWindow->clone(ui::LogicalDisplayId::DEFAULT);
11102 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Vishnu Nair958da932020-08-21 17:12:37 -070011103 mWindow->setFocusable(true);
11104 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011105 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011106 }
11107};
11108
11109TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
11110 // Request focus on a mirrored window
11111 setFocusedWindow(mMirror);
11112
11113 // window gets focused
11114 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011115 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011116 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011117 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011118}
11119
11120// A focused & mirrored window remains focused only if the window and its mirror are both
11121// focusable.
11122TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
11123 setFocusedWindow(mMirror);
11124
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000011125 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -070011126 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011127 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011128 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011129 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011130 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011131 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011132 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011133
11134 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011135 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011136
11137 // window loses focus since one of the windows associated with the token in not focusable
11138 mWindow->consumeFocusEvent(false);
11139
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011140 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011141 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011142 mWindow->assertNoEvents();
11143}
11144
11145// A focused & mirrored window remains focused until the window and its mirror both become
11146// invisible.
11147TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
11148 setFocusedWindow(mMirror);
11149
11150 // window gets focused
11151 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011153 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011154 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011155 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011156 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011157 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011158
11159 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011160 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011161
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011162 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011163 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011164 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011166 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011167 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011168
11169 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011170 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011171
11172 // window loses focus only after all windows associated with the token become invisible.
11173 mWindow->consumeFocusEvent(false);
11174
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011175 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011176 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011177 mWindow->assertNoEvents();
11178}
11179
11180// A focused & mirrored window remains focused until both windows are removed.
11181TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
11182 setFocusedWindow(mMirror);
11183
11184 // window gets focused
11185 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011186 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011187 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011188 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011190 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011191 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011192
11193 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011194 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011195
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011196 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011197 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011198 mMirror->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011199 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011200 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011201 mMirror->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011202
11203 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011204 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011205 mWindow->consumeFocusEvent(false);
11206
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011207 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011208 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011209 mWindow->assertNoEvents();
11210}
11211
11212// Focus request can be pending until one window becomes visible.
11213TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
11214 // Request focus on an invisible mirror.
11215 mWindow->setVisible(false);
11216 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011217 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011218 setFocusedWindow(mMirror);
11219
11220 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011222 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011223 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -070011224
11225 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011226 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011227
11228 // window gets focused
11229 mWindow->consumeFocusEvent(true);
11230 // window gets the pending key event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011231 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -070011232}
Prabir Pradhan99987712020-11-10 18:43:05 -080011233
11234class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
11235protected:
11236 std::shared_ptr<FakeApplicationHandle> mApp;
11237 sp<FakeWindowHandle> mWindow;
11238 sp<FakeWindowHandle> mSecondWindow;
11239
11240 void SetUp() override {
11241 InputDispatcherTest::SetUp();
11242 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011243 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11244 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080011245 mWindow->setFocusable(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011246 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11247 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080011248 mSecondWindow->setFocusable(true);
11249
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011250 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011251 mDispatcher->onWindowInfosChanged(
11252 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -080011253
11254 setFocusedWindow(mWindow);
11255 mWindow->consumeFocusEvent(true);
11256 }
11257
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011258 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011259 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -080011260 }
11261
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011262 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
11263 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -080011264 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +090011265 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011266 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011267 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011268 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -080011269 }
11270};
11271
11272TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
11273 // Ensure that capture cannot be obtained for unfocused windows.
11274 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11275 mFakePolicy->assertSetPointerCaptureNotCalled();
11276 mSecondWindow->assertNoEvents();
11277
11278 // Ensure that capture can be enabled from the focus window.
11279 requestAndVerifyPointerCapture(mWindow, true);
11280
11281 // Ensure that capture cannot be disabled from a window that does not have capture.
11282 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
11283 mFakePolicy->assertSetPointerCaptureNotCalled();
11284
11285 // Ensure that capture can be disabled from the window with capture.
11286 requestAndVerifyPointerCapture(mWindow, false);
11287}
11288
11289TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011290 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011291
11292 setFocusedWindow(mSecondWindow);
11293
11294 // Ensure that the capture disabled event was sent first.
11295 mWindow->consumeCaptureEvent(false);
11296 mWindow->consumeFocusEvent(false);
11297 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +090011298 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011299
11300 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011301 notifyPointerCaptureChanged({});
11302 notifyPointerCaptureChanged(request);
11303 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -080011304 mWindow->assertNoEvents();
11305 mSecondWindow->assertNoEvents();
11306 mFakePolicy->assertSetPointerCaptureNotCalled();
11307}
11308
11309TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011310 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011311
11312 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011313 notifyPointerCaptureChanged({});
11314 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011315
11316 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +090011317 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011318 mWindow->consumeCaptureEvent(false);
11319 mWindow->assertNoEvents();
11320}
11321
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011322TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
11323 requestAndVerifyPointerCapture(mWindow, true);
11324
11325 // The first window loses focus.
11326 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +090011327 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011328 mWindow->consumeCaptureEvent(false);
11329
11330 // Request Pointer Capture from the second window before the notification from InputReader
11331 // arrives.
11332 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011333 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011334
11335 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011336 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011337
11338 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011339 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011340
11341 mSecondWindow->consumeFocusEvent(true);
11342 mSecondWindow->consumeCaptureEvent(true);
11343}
11344
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011345TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
11346 // App repeatedly enables and disables capture.
11347 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011348 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011349 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011350 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011351 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011352 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011353
11354 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
11355 // first request is now stale, this should do nothing.
11356 notifyPointerCaptureChanged(firstRequest);
11357 mWindow->assertNoEvents();
11358
11359 // InputReader notifies that the second request was enabled.
11360 notifyPointerCaptureChanged(secondRequest);
11361 mWindow->consumeCaptureEvent(true);
11362}
11363
Prabir Pradhan7092e262022-05-03 16:51:09 +000011364TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
11365 requestAndVerifyPointerCapture(mWindow, true);
11366
11367 // App toggles pointer capture off and on.
11368 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011369 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011370
11371 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011372 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011373
11374 // InputReader notifies that the latest "enable" request was processed, while skipping over the
11375 // preceding "disable" request.
11376 notifyPointerCaptureChanged(enableRequest);
11377
11378 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
11379 // any notifications.
11380 mWindow->assertNoEvents();
11381}
11382
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011383/**
11384 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
11385 * mouse movements don't affect the previous mouse hovering state.
11386 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
11387 * HOVER_MOVE events).
11388 */
11389TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
11390 // Mouse hover on the window
11391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11392 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11393 .build());
11394 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11395 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11396 .build());
11397
11398 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
11399 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
11400
11401 // Start pointer capture
11402 requestAndVerifyPointerCapture(mWindow, true);
11403
11404 // Send some relative mouse movements and receive them in the window.
11405 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
11406 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
11407 .build());
11408 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
11409 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
11410
11411 // Stop pointer capture
11412 requestAndVerifyPointerCapture(mWindow, false);
11413
11414 // Continue hovering on the window
11415 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11416 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
11417 .build());
11418 mWindow->consumeMotionEvent(
11419 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
11420
11421 mWindow->assertNoEvents();
11422}
11423
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011424TEST_F(InputDispatcherPointerCaptureTests, MultiDisplayPointerCapture) {
11425 // The default display is the focused display to begin with.
11426 requestAndVerifyPointerCapture(mWindow, true);
11427
11428 // Move the second window to a second display, make it the focused window on that display.
11429 mSecondWindow->editInfo()->displayId = SECOND_DISPLAY_ID;
11430 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11431 setFocusedWindow(mSecondWindow);
11432 mSecondWindow->consumeFocusEvent(true);
11433
11434 mWindow->assertNoEvents();
11435
11436 // The second window cannot gain capture because it is not on the focused display.
11437 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11438 mFakePolicy->assertSetPointerCaptureNotCalled();
11439 mSecondWindow->assertNoEvents();
11440
11441 // Make the second display the focused display.
11442 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +000011443 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011444
11445 // This causes the first window to lose pointer capture, and it's unable to request capture.
11446 mWindow->consumeCaptureEvent(false);
11447 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11448
11449 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11450 mFakePolicy->assertSetPointerCaptureNotCalled();
11451
11452 // The second window is now able to gain pointer capture successfully.
11453 requestAndVerifyPointerCapture(mSecondWindow, true);
11454}
11455
Hiroki Sato25040232024-02-22 17:21:22 +090011456using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
11457
11458TEST_F(InputDispatcherPointerCaptureDeathTest,
11459 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
11460 testing::GTEST_FLAG(death_test_style) = "threadsafe";
11461 ScopedSilentDeath _silentDeath;
11462
11463 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11464 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11465
11466 // Dispatch a pointer changed event with a wrong token.
11467 request.window = mSecondWindow->getToken();
11468 ASSERT_DEATH(
11469 {
11470 notifyPointerCaptureChanged(request);
11471 mSecondWindow->consumeCaptureEvent(true);
11472 },
11473 "Unexpected requested window for Pointer Capture.");
11474}
11475
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011476class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
11477protected:
11478 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000011479
11480 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
11481 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
11482
11483 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
11484 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11485
11486 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
11487 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
11488 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11489 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
11490 MAXIMUM_OBSCURING_OPACITY);
11491
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011492 static constexpr gui::Uid TOUCHED_APP_UID{10001};
11493 static constexpr gui::Uid APP_B_UID{10002};
11494 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011495
11496 sp<FakeWindowHandle> mTouchWindow;
11497
11498 virtual void SetUp() override {
11499 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011500 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011501 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
11502 }
11503
11504 virtual void TearDown() override {
11505 InputDispatcherTest::TearDown();
11506 mTouchWindow.clear();
11507 }
11508
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011509 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050011510 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011511 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011512 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011513 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011514 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011515 return window;
11516 }
11517
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011518 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011519 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
11520 sp<FakeWindowHandle> window =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011521 sp<FakeWindowHandle>::make(app, mDispatcher, name, ui::LogicalDisplayId::DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011522 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011523 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011524 return window;
11525 }
11526
11527 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011528 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011529 AINPUT_SOURCE_TOUCHSCREEN,
11530 ui::LogicalDisplayId::DEFAULT, points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011531 }
11532};
11533
11534TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011535 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011536 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011537 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011538
11539 touch();
11540
11541 mTouchWindow->assertNoEvents();
11542}
11543
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011544TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000011545 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
11546 const sp<FakeWindowHandle>& w =
11547 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011548 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011549
11550 touch();
11551
11552 mTouchWindow->assertNoEvents();
11553}
11554
11555TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011556 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
11557 const sp<FakeWindowHandle>& w =
11558 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011559 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011560
11561 touch();
11562
11563 w->assertNoEvents();
11564}
11565
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011566TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011567 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011568 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011569
11570 touch();
11571
11572 mTouchWindow->consumeAnyMotionDown();
11573}
11574
11575TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011576 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011577 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011578 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011579 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011580
11581 touch({PointF{100, 100}});
11582
11583 mTouchWindow->consumeAnyMotionDown();
11584}
11585
11586TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011587 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011588 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011589 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011590
11591 touch();
11592
11593 mTouchWindow->consumeAnyMotionDown();
11594}
11595
11596TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
11597 const sp<FakeWindowHandle>& w =
11598 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011599 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011600
11601 touch();
11602
11603 mTouchWindow->consumeAnyMotionDown();
11604}
11605
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011606TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
11607 const sp<FakeWindowHandle>& w =
11608 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011609 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011610
11611 touch();
11612
11613 w->assertNoEvents();
11614}
11615
11616/**
11617 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
11618 * inside) while letting them pass-through. Note that even though touch passes through the occluding
11619 * window, the occluding window will still receive ACTION_OUTSIDE event.
11620 */
11621TEST_F(InputDispatcherUntrustedTouchesTest,
11622 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
11623 const sp<FakeWindowHandle>& w =
11624 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011625 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011626 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011627
11628 touch();
11629
11630 w->consumeMotionOutside();
11631}
11632
11633TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
11634 const sp<FakeWindowHandle>& w =
11635 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011636 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011637 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011638
11639 touch();
11640
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011641 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011642}
11643
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011644TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011645 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011646 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11647 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011648 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011649
11650 touch();
11651
11652 mTouchWindow->consumeAnyMotionDown();
11653}
11654
11655TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
11656 const sp<FakeWindowHandle>& w =
11657 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11658 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011659 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011660
11661 touch();
11662
11663 mTouchWindow->consumeAnyMotionDown();
11664}
11665
11666TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011667 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011668 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11669 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011670 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011671
11672 touch();
11673
11674 mTouchWindow->assertNoEvents();
11675}
11676
11677TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
11678 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
11679 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011680 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11681 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011682 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011683 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11684 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011685 mDispatcher->onWindowInfosChanged(
11686 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011687
11688 touch();
11689
11690 mTouchWindow->assertNoEvents();
11691}
11692
11693TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
11694 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
11695 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011696 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11697 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011698 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011699 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11700 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011701 mDispatcher->onWindowInfosChanged(
11702 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011703
11704 touch();
11705
11706 mTouchWindow->consumeAnyMotionDown();
11707}
11708
11709TEST_F(InputDispatcherUntrustedTouchesTest,
11710 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
11711 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011712 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11713 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011714 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011715 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11716 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011717 mDispatcher->onWindowInfosChanged(
11718 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011719
11720 touch();
11721
11722 mTouchWindow->consumeAnyMotionDown();
11723}
11724
11725TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
11726 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011727 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11728 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011729 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011730 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11731 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011732 mDispatcher->onWindowInfosChanged(
11733 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011734
11735 touch();
11736
11737 mTouchWindow->assertNoEvents();
11738}
11739
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011740TEST_F(InputDispatcherUntrustedTouchesTest,
11741 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
11742 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011743 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11744 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011745 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011746 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11747 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011748 mDispatcher->onWindowInfosChanged(
11749 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011750
11751 touch();
11752
11753 mTouchWindow->assertNoEvents();
11754}
11755
11756TEST_F(InputDispatcherUntrustedTouchesTest,
11757 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
11758 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011759 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11760 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011761 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011762 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11763 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011764 mDispatcher->onWindowInfosChanged(
11765 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011766
11767 touch();
11768
11769 mTouchWindow->consumeAnyMotionDown();
11770}
11771
11772TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
11773 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011774 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11775 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011776 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011777
11778 touch();
11779
11780 mTouchWindow->consumeAnyMotionDown();
11781}
11782
11783TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
11784 const sp<FakeWindowHandle>& w =
11785 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011786 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011787
11788 touch();
11789
11790 mTouchWindow->consumeAnyMotionDown();
11791}
11792
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011793TEST_F(InputDispatcherUntrustedTouchesTest,
11794 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
11795 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11796 const sp<FakeWindowHandle>& w =
11797 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011798 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011799
11800 touch();
11801
11802 mTouchWindow->assertNoEvents();
11803}
11804
11805TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
11806 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11807 const sp<FakeWindowHandle>& w =
11808 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011809 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011810
11811 touch();
11812
11813 mTouchWindow->consumeAnyMotionDown();
11814}
11815
11816TEST_F(InputDispatcherUntrustedTouchesTest,
11817 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
11818 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
11819 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011820 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11821 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011822 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011823
11824 touch();
11825
11826 mTouchWindow->consumeAnyMotionDown();
11827}
11828
11829TEST_F(InputDispatcherUntrustedTouchesTest,
11830 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
11831 const sp<FakeWindowHandle>& w1 =
11832 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11833 OPACITY_BELOW_THRESHOLD);
11834 const sp<FakeWindowHandle>& w2 =
11835 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11836 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011837 mDispatcher->onWindowInfosChanged(
11838 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011839
11840 touch();
11841
11842 mTouchWindow->assertNoEvents();
11843}
11844
11845/**
11846 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
11847 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
11848 * (which alone would result in allowing touches) does not affect the blocking behavior.
11849 */
11850TEST_F(InputDispatcherUntrustedTouchesTest,
11851 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
11852 const sp<FakeWindowHandle>& wB =
11853 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11854 OPACITY_BELOW_THRESHOLD);
11855 const sp<FakeWindowHandle>& wC =
11856 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11857 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011858 mDispatcher->onWindowInfosChanged(
11859 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011860
11861 touch();
11862
11863 mTouchWindow->assertNoEvents();
11864}
11865
11866/**
11867 * This test is testing that a window from a different UID but with same application token doesn't
11868 * block the touch. Apps can share the application token for close UI collaboration for example.
11869 */
11870TEST_F(InputDispatcherUntrustedTouchesTest,
11871 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
11872 const sp<FakeWindowHandle>& w =
11873 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
11874 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011875 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011876
11877 touch();
11878
11879 mTouchWindow->consumeAnyMotionDown();
11880}
11881
arthurhungb89ccb02020-12-30 16:19:01 +080011882class InputDispatcherDragTests : public InputDispatcherTest {
11883protected:
11884 std::shared_ptr<FakeApplicationHandle> mApp;
11885 sp<FakeWindowHandle> mWindow;
11886 sp<FakeWindowHandle> mSecondWindow;
11887 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011888 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011889 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
11890 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080011891
11892 void SetUp() override {
11893 InputDispatcherTest::SetUp();
11894 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011895 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11896 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011897 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011898
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011899 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11900 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011901 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011902
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011903 mSpyWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow",
11904 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011905 mSpyWindow->setSpy(true);
11906 mSpyWindow->setTrustedOverlay(true);
11907 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
11908
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011909 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011910 mDispatcher->onWindowInfosChanged(
11911 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
11912 {},
11913 0,
11914 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011915 }
11916
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011917 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
11918 switch (fromSource) {
11919 case AINPUT_SOURCE_TOUCHSCREEN:
11920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011921 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011922 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011923 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11924 break;
11925 case AINPUT_SOURCE_STYLUS:
11926 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011927 injectMotionEvent(*mDispatcher,
11928 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11929 AINPUT_SOURCE_STYLUS)
11930 .buttonState(
11931 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
11932 .pointer(PointerBuilder(0, ToolType::STYLUS)
11933 .x(50)
11934 .y(50))
11935 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011936 break;
11937 case AINPUT_SOURCE_MOUSE:
11938 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011939 injectMotionEvent(*mDispatcher,
11940 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11941 AINPUT_SOURCE_MOUSE)
11942 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
11943 .pointer(PointerBuilder(MOUSE_POINTER_ID,
11944 ToolType::MOUSE)
11945 .x(50)
11946 .y(50))
11947 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011948 break;
11949 default:
11950 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
11951 }
arthurhungb89ccb02020-12-30 16:19:01 +080011952
11953 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011954 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011955 // Spy window should also receive motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011956 mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011957 }
11958
11959 // Start performing drag, we will create a drag window and transfer touch to it.
11960 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
11961 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011962 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000011963 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011964 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000011965 }
arthurhungb89ccb02020-12-30 16:19:01 +080011966
11967 // The drag window covers the entire display
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011968 mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow",
11969 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011970 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011971 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
11972 *mWindow->getInfo(), *mSecondWindow->getInfo()},
11973 {},
11974 0,
11975 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011976
11977 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000011978 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000011979 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
11980 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000011981 if (transferred) {
11982 mWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011983 mDragWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
11984 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000011985 }
11986 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080011987 }
11988};
11989
11990TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011991 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080011992
11993 // Move on window.
11994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011995 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011996 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011997 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011998 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11999 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012000 mWindow->consumeDragEvent(false, 50, 50);
12001 mSecondWindow->assertNoEvents();
12002
12003 // Move to another window.
12004 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012005 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012006 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012007 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012008 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12009 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012010 mWindow->consumeDragEvent(true, 150, 50);
12011 mSecondWindow->consumeDragEvent(false, 50, 50);
12012
12013 // Move back to original window.
12014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012015 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012016 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012018 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12019 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012020 mWindow->consumeDragEvent(false, 50, 50);
12021 mSecondWindow->consumeDragEvent(true, -50, 50);
12022
12023 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012024 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012025 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012026 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012027 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012028 mWindow->assertNoEvents();
12029 mSecondWindow->assertNoEvents();
12030}
12031
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012032TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012033 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012034
12035 // No cancel event after drag start
12036 mSpyWindow->assertNoEvents();
12037
12038 const MotionEvent secondFingerDownEvent =
12039 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12040 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012041 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12042 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012043 .build();
12044 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012045 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012046 InputEventInjectionSync::WAIT_FOR_RESULT))
12047 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12048
12049 // Receives cancel for first pointer after next pointer down
12050 mSpyWindow->consumeMotionCancel();
12051 mSpyWindow->consumeMotionDown();
12052
12053 mSpyWindow->assertNoEvents();
12054}
12055
arthurhungf452d0b2021-01-06 00:19:52 +080012056TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012057 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080012058
12059 // Move on window.
12060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012061 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012062 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080012063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012064 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12065 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080012066 mWindow->consumeDragEvent(false, 50, 50);
12067 mSecondWindow->assertNoEvents();
12068
12069 // Move to another window.
12070 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012071 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012072 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080012073 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012074 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12075 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080012076 mWindow->consumeDragEvent(true, 150, 50);
12077 mSecondWindow->consumeDragEvent(false, 50, 50);
12078
12079 // drop to another window.
12080 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012081 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080012082 {150, 50}))
12083 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012084 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012085 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080012086 mWindow->assertNoEvents();
12087 mSecondWindow->assertNoEvents();
12088}
12089
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012090TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
12091 startDrag();
12092
12093 // No cancel event after drag start
12094 mSpyWindow->assertNoEvents();
12095
12096 const MotionEvent secondFingerDownEvent =
12097 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12098 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12099 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12100 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
12101 .build();
12102 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12103 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12104 InputEventInjectionSync::WAIT_FOR_RESULT))
12105 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12106
12107 // Receives cancel for first pointer after next pointer down
12108 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080012109 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012110 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
12111
12112 mSpyWindow->assertNoEvents();
12113
12114 // Spy window calls pilfer pointers
12115 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
12116 mDragWindow->assertNoEvents();
12117
12118 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080012119 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012120 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12121 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
12122 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
12123 .build();
12124 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080012125 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012126 InputEventInjectionSync::WAIT_FOR_RESULT))
12127 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12128
12129 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000012130 mDragWindow->consumeMotionEvent(
12131 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012132 mDragWindow->assertNoEvents();
12133}
12134
arthurhung6d4bed92021-03-17 11:59:33 +080012135TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012136 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080012137
12138 // Move on window and keep button pressed.
12139 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012140 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012141 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
12142 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012143 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012144 .build()))
12145 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012146 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12147 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012148 mWindow->consumeDragEvent(false, 50, 50);
12149 mSecondWindow->assertNoEvents();
12150
12151 // Move to another window and release button, expect to drop item.
12152 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012153 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012154 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
12155 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012156 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012157 .build()))
12158 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012159 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12160 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012161 mWindow->assertNoEvents();
12162 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012163 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080012164
12165 // nothing to the window.
12166 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012167 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012168 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
12169 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012170 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012171 .build()))
12172 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012173 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012174 mWindow->assertNoEvents();
12175 mSecondWindow->assertNoEvents();
12176}
12177
Arthur Hung54745652022-04-20 07:17:41 +000012178TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012179 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080012180
12181 // Set second window invisible.
12182 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012183 mDispatcher->onWindowInfosChanged(
12184 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080012185
12186 // Move on window.
12187 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012188 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012189 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080012190 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012191 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12192 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012193 mWindow->consumeDragEvent(false, 50, 50);
12194 mSecondWindow->assertNoEvents();
12195
12196 // Move to another window.
12197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012198 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012199 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080012200 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012201 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12202 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012203 mWindow->consumeDragEvent(true, 150, 50);
12204 mSecondWindow->assertNoEvents();
12205
12206 // drop to another window.
12207 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012208 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080012209 {150, 50}))
12210 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012211 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012212 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012213 mWindow->assertNoEvents();
12214 mSecondWindow->assertNoEvents();
12215}
12216
Arthur Hung54745652022-04-20 07:17:41 +000012217TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012218 // Ensure window could track pointerIds if it didn't support split touch.
12219 mWindow->setPreventSplitting(true);
12220
Arthur Hung54745652022-04-20 07:17:41 +000012221 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012222 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12223 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000012224 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012225 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012226
12227 const MotionEvent secondFingerDownEvent =
12228 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012229 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000012230 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012231 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12232 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012233 .build();
12234 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012235 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012236 InputEventInjectionSync::WAIT_FOR_RESULT))
12237 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000012238 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000012239
12240 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012241 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000012242}
12243
12244TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
12245 // First down on second window.
12246 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012247 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12248 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000012249 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12250
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012251 mSecondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012252
12253 // Second down on first window.
12254 const MotionEvent secondFingerDownEvent =
12255 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012256 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000012257 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012258 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12259 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012260 .build();
12261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012262 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012263 InputEventInjectionSync::WAIT_FOR_RESULT))
12264 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012265 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12266 mSecondWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012267
12268 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012269 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000012270
12271 // Move on window.
12272 const MotionEvent secondFingerMoveEvent =
12273 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12274 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012275 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12276 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012277 .build();
12278 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012279 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012280 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012281 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12282 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000012283 mWindow->consumeDragEvent(false, 50, 50);
12284 mSecondWindow->consumeMotionMove();
12285
12286 // Release the drag pointer should perform drop.
12287 const MotionEvent secondFingerUpEvent =
12288 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12289 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012290 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12291 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012292 .build();
12293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012294 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012295 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012296 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012297 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000012298 mWindow->assertNoEvents();
12299 mSecondWindow->consumeMotionMove();
12300}
12301
Arthur Hung3915c1f2022-05-31 07:17:17 +000012302TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012303 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000012304
12305 // Update window of second display.
12306 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012307 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012308 mDispatcher->onWindowInfosChanged(
12309 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12310 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12311 {},
12312 0,
12313 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012314
12315 // Let second display has a touch state.
12316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012317 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012318 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12319 AINPUT_SOURCE_TOUCHSCREEN)
12320 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012321 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012322 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000012323 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012324 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012325 mDispatcher->onWindowInfosChanged(
12326 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12327 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12328 {},
12329 0,
12330 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012331
12332 // Move on window.
12333 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012334 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012335 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012336 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012337 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12338 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012339 mWindow->consumeDragEvent(false, 50, 50);
12340 mSecondWindow->assertNoEvents();
12341
12342 // Move to another window.
12343 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012344 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012345 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012346 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012347 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12348 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012349 mWindow->consumeDragEvent(true, 150, 50);
12350 mSecondWindow->consumeDragEvent(false, 50, 50);
12351
12352 // drop to another window.
12353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012354 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012355 {150, 50}))
12356 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012357 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012358 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000012359 mWindow->assertNoEvents();
12360 mSecondWindow->assertNoEvents();
12361}
12362
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012363TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
12364 startDrag(true, AINPUT_SOURCE_MOUSE);
12365 // Move on window.
12366 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012367 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012368 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12369 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012370 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012371 .x(50)
12372 .y(50))
12373 .build()))
12374 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012375 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12376 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012377 mWindow->consumeDragEvent(false, 50, 50);
12378 mSecondWindow->assertNoEvents();
12379
12380 // Move to another window.
12381 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012382 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012383 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12384 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012385 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012386 .x(150)
12387 .y(50))
12388 .build()))
12389 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012390 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12391 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012392 mWindow->consumeDragEvent(true, 150, 50);
12393 mSecondWindow->consumeDragEvent(false, 50, 50);
12394
12395 // drop to another window.
12396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012397 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012398 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
12399 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012400 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012401 .x(150)
12402 .y(50))
12403 .build()))
12404 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012405 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012406 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012407 mWindow->assertNoEvents();
12408 mSecondWindow->assertNoEvents();
12409}
12410
Linnan Li5af92f92023-07-14 14:36:22 +080012411/**
12412 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
12413 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
12414 */
12415TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
12416 // Down on second window
12417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012418 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12419 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012420 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12421
12422 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
12423 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
12424
12425 // Down on first window
12426 const MotionEvent secondFingerDownEvent =
12427 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012428 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012429 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12430 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12431 .build();
12432 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12433 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12434 InputEventInjectionSync::WAIT_FOR_RESULT))
12435 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12436 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12437 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
12438 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
12439
12440 // Start drag on first window
12441 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
12442
12443 // Trigger cancel
12444 mDispatcher->cancelCurrentTouch();
12445 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012446 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +000012447 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080012448 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
12449
12450 ASSERT_TRUE(mDispatcher->waitForIdle());
12451 // The D&D finished with nullptr
12452 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
12453
12454 // Remove drag window
12455 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
12456
12457 // Inject a simple gesture, ensure dispatcher not crashed
12458 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012459 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12460 ui::LogicalDisplayId::DEFAULT, PointF{50, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012461 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12462 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12463
12464 const MotionEvent moveEvent =
12465 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012466 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012467 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12468 .build();
12469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12470 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
12471 InputEventInjectionSync::WAIT_FOR_RESULT))
12472 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12473 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
12474
12475 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012476 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Li5af92f92023-07-14 14:36:22 +080012477 {50, 50}))
12478 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12479 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
12480}
12481
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012482TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
12483 // Start hovering over the window.
12484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12485 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012486 ui::LogicalDisplayId::DEFAULT, {50, 50}));
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012487
12488 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12489 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12490
12491 ASSERT_FALSE(startDrag(/*sendDown=*/false))
12492 << "Drag and drop should not work with a hovering pointer";
12493}
12494
Vishnu Nair062a8672021-09-03 16:07:44 -070012495class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
12496
12497TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
12498 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012499 sp<FakeWindowHandle> window =
12500 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12501 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012502 window->setDropInput(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012503 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012504 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012505 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012506 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012507 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012508
12509 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012510 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012511 window->assertNoEvents();
12512
Prabir Pradhan678438e2023-04-13 19:32:51 +000012513 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012514 AINPUT_SOURCE_TOUCHSCREEN,
12515 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012516 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012517 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080012518 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070012519 window->assertNoEvents();
12520
12521 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012522 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012523 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012524
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012525 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12526 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012527
Prabir Pradhan678438e2023-04-13 19:32:51 +000012528 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012529 AINPUT_SOURCE_TOUCHSCREEN,
12530 ui::LogicalDisplayId::DEFAULT));
12531 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012532 window->assertNoEvents();
12533}
12534
12535TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
12536 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12537 std::make_shared<FakeApplicationHandle>();
12538 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012539 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012540 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012541 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012542 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012543 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012544 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012545 sp<FakeWindowHandle> window =
12546 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12547 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012548 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012549 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012550 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012551 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012552 mDispatcher->onWindowInfosChanged(
12553 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012554 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012555 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012556
12557 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012558 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012559 window->assertNoEvents();
12560
Prabir Pradhan678438e2023-04-13 19:32:51 +000012561 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012562 AINPUT_SOURCE_TOUCHSCREEN,
12563 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012564 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012565 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012566 window->assertNoEvents();
12567
12568 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012569 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012570 mDispatcher->onWindowInfosChanged(
12571 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012572
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012573 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12574 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012575
Prabir Pradhan678438e2023-04-13 19:32:51 +000012576 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012577 AINPUT_SOURCE_TOUCHSCREEN,
12578 ui::LogicalDisplayId::DEFAULT));
12579 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
12580 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Vishnu Nair062a8672021-09-03 16:07:44 -070012581 window->assertNoEvents();
12582}
12583
12584TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
12585 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12586 std::make_shared<FakeApplicationHandle>();
12587 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012588 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012589 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012590 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012591 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012592 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012593 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012594 sp<FakeWindowHandle> window =
12595 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12596 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012597 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012598 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012599 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012600 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012601 mDispatcher->onWindowInfosChanged(
12602 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012603 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012604 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012605
12606 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012607 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012608 window->assertNoEvents();
12609
Prabir Pradhan678438e2023-04-13 19:32:51 +000012610 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012611 AINPUT_SOURCE_TOUCHSCREEN,
12612 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012613 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012614 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012615 window->assertNoEvents();
12616
12617 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012618 mDispatcher->onWindowInfosChanged(
12619 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012620
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012621 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12622 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012623
Prabir Pradhan678438e2023-04-13 19:32:51 +000012624 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012625 AINPUT_SOURCE_TOUCHSCREEN,
12626 ui::LogicalDisplayId::DEFAULT));
12627 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012628 window->assertNoEvents();
12629}
12630
Antonio Kantekf16f2832021-09-28 04:39:20 +000012631class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
12632protected:
12633 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000012634 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012635 sp<FakeWindowHandle> mWindow;
12636 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000012637 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012638
12639 void SetUp() override {
12640 InputDispatcherTest::SetUp();
12641
12642 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000012643 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012644 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
12645 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012646 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012647 setFocusedWindow(mWindow);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012648 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
12649 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012650 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000012651 mThirdWindow =
12652 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
12653 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
12654 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012655
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012656 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012657 mDispatcher->onWindowInfosChanged(
12658 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
12659 {},
12660 0,
12661 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000012662 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012663 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012664
Antonio Kantek15beb512022-06-13 22:35:41 +000012665 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012666 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012667 WINDOW_UID, /*hasPermission=*/true,
12668 ui::LogicalDisplayId::DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070012669 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
12670 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012671 mThirdWindow->assertNoEvents();
12672 }
12673
12674 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
12675 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000012676 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000012677 SECOND_DISPLAY_ID)) {
12678 mWindow->assertNoEvents();
12679 mSecondWindow->assertNoEvents();
12680 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070012681 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000012682 }
12683
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012684 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000012685 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070012686 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012687 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012688 mWindow->consumeTouchModeEvent(inTouchMode);
12689 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012690 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000012691 }
12692};
12693
Antonio Kantek26defcf2022-02-08 01:12:27 +000012694TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012695 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000012696 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
12697 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012698 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012699}
12700
Antonio Kantek26defcf2022-02-08 01:12:27 +000012701TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
12702 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012703 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012704 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012705 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012706 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012707 ownerUid, /*hasPermission=*/false,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012708 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000012709 mWindow->assertNoEvents();
12710 mSecondWindow->assertNoEvents();
12711}
12712
12713TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
12714 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012715 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012716 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012717 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000012718 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012719 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012720}
12721
Antonio Kantekf16f2832021-09-28 04:39:20 +000012722TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012723 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000012724 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
12725 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012726 /*hasPermission=*/true,
12727 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012728 mWindow->assertNoEvents();
12729 mSecondWindow->assertNoEvents();
12730}
12731
Antonio Kantek15beb512022-06-13 22:35:41 +000012732TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
12733 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
12734 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12735 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012736 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000012737 mWindow->assertNoEvents();
12738 mSecondWindow->assertNoEvents();
12739 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
12740}
12741
Antonio Kantek48710e42022-03-24 14:19:30 -070012742TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
12743 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012744 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012745 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070012746 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012747 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Antonio Kantek48710e42022-03-24 14:19:30 -070012748
12749 // Then remove focus.
12750 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012751 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070012752
12753 // Assert that caller can switch touch mode by owning one of the last interacted window.
12754 const WindowInfo& windowInfo = *mWindow->getInfo();
12755 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12756 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012757 /*hasPermission=*/false,
12758 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070012759}
12760
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012761class InputDispatcherSpyWindowTest : public InputDispatcherTest {
12762public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012763 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012764 std::shared_ptr<FakeApplicationHandle> application =
12765 std::make_shared<FakeApplicationHandle>();
12766 std::string name = "Fake Spy ";
12767 name += std::to_string(mSpyCount++);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012768 sp<FakeWindowHandle> spy =
12769 sp<FakeWindowHandle>::make(application, mDispatcher, name.c_str(),
12770 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012771 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012772 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012773 return spy;
12774 }
12775
12776 sp<FakeWindowHandle> createForeground() {
12777 std::shared_ptr<FakeApplicationHandle> application =
12778 std::make_shared<FakeApplicationHandle>();
12779 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012780 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012781 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012782 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012783 return window;
12784 }
12785
12786private:
12787 int mSpyCount{0};
12788};
12789
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012790using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012791/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012792 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
12793 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012794TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070012795 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012796 ScopedSilentDeath _silentDeath;
12797
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012798 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012799 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012800 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012801 ".* not a trusted overlay");
12802}
12803
12804/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012805 * Input injection into a display with a spy window but no foreground windows should succeed.
12806 */
12807TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012808 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012809 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012810
12811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012812 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12813 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012814 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012815 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012816}
12817
12818/**
12819 * Verify the order in which different input windows receive events. The touched foreground window
12820 * (if there is one) should always receive the event first. When there are multiple spy windows, the
12821 * spy windows will receive the event according to their Z-order, where the top-most spy window will
12822 * receive events before ones belows it.
12823 *
12824 * Here, we set up a scenario with four windows in the following Z order from the top:
12825 * spy1, spy2, window, spy3.
12826 * We then inject an event and verify that the foreground "window" receives it first, followed by
12827 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
12828 * window.
12829 */
12830TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
12831 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012832 auto spy1 = createSpy();
12833 auto spy2 = createSpy();
12834 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012835 mDispatcher->onWindowInfosChanged(
12836 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012837 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
12838 const size_t numChannels = channels.size();
12839
Michael Wright8e9a8562022-02-09 13:44:29 +000012840 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012841 if (!epollFd.ok()) {
12842 FAIL() << "Failed to create epoll fd";
12843 }
12844
12845 for (size_t i = 0; i < numChannels; i++) {
12846 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
12847 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
12848 FAIL() << "Failed to add fd to epoll";
12849 }
12850 }
12851
12852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012853 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12854 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012855 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12856
12857 std::vector<size_t> eventOrder;
12858 std::vector<struct epoll_event> events(numChannels);
12859 for (;;) {
12860 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
12861 (100ms).count());
12862 if (nFds < 0) {
12863 FAIL() << "Failed to call epoll_wait";
12864 }
12865 if (nFds == 0) {
12866 break; // epoll_wait timed out
12867 }
12868 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070012869 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070012870 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012871 channels[i]->consumeMotionDown();
12872 }
12873 }
12874
12875 // Verify the order in which the events were received.
12876 EXPECT_EQ(3u, eventOrder.size());
12877 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
12878 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
12879 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
12880}
12881
12882/**
12883 * A spy window using the NOT_TOUCHABLE flag does not receive events.
12884 */
12885TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
12886 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012887 auto spy = createSpy();
12888 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012889 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012890
12891 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012892 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12893 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012894 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012895 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012896 spy->assertNoEvents();
12897}
12898
12899/**
12900 * A spy window will only receive gestures that originate within its touchable region. Gestures that
12901 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
12902 * to the window.
12903 */
12904TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
12905 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012906 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012907 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012908 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012909
12910 // Inject an event outside the spy window's touchable region.
12911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012912 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12913 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12915 window->consumeMotionDown();
12916 spy->assertNoEvents();
12917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012918 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12919 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012920 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12921 window->consumeMotionUp();
12922 spy->assertNoEvents();
12923
12924 // Inject an event inside the spy window's touchable region.
12925 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012926 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12927 ui::LogicalDisplayId::DEFAULT, {5, 10}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012928 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12929 window->consumeMotionDown();
12930 spy->consumeMotionDown();
12931}
12932
12933/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012934 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012935 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012936 */
12937TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
12938 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012939 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012940 auto spy = createSpy();
12941 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012942 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012943 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012944 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012945
12946 // Inject an event outside the spy window's frame and touchable region.
12947 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012948 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12949 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012950 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12951 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012952 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012953}
12954
12955/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012956 * Even when a spy window spans over multiple foreground windows, the spy should receive all
12957 * pointers that are down within its bounds.
12958 */
12959TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
12960 auto windowLeft = createForeground();
12961 windowLeft->setFrame({0, 0, 100, 200});
12962 auto windowRight = createForeground();
12963 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012964 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012965 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012966 mDispatcher->onWindowInfosChanged(
12967 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012968
12969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012970 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12971 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012972 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12973 windowLeft->consumeMotionDown();
12974 spy->consumeMotionDown();
12975
12976 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012977 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012978 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012979 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12980 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012981 .build();
12982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012983 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012984 InputEventInjectionSync::WAIT_FOR_RESULT))
12985 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12986 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000012987 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012988}
12989
12990/**
12991 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
12992 * the spy should receive the second pointer with ACTION_DOWN.
12993 */
12994TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
12995 auto window = createForeground();
12996 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012997 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012998 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012999 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013000
13001 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013002 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13003 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013004 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13005 window->consumeMotionDown();
13006 spyRight->assertNoEvents();
13007
13008 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080013009 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013010 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013011 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13012 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013013 .build();
13014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013015 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013016 InputEventInjectionSync::WAIT_FOR_RESULT))
13017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000013018 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013019 spyRight->consumeMotionDown();
13020}
13021
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013022/**
13023 * The spy window should not be able to affect whether or not touches are split. Only the foreground
13024 * windows should be allowed to control split touch.
13025 */
13026TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080013027 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013028 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013029 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080013030 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013031
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013032 auto window = createForeground();
13033 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013034
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013035 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013036
13037 // First finger down, no window touched.
13038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013039 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13040 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013041 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013042 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013043 window->assertNoEvents();
13044
13045 // Second finger down on window, the window should receive touch down.
13046 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080013047 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013048 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013049 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013050 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13051 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013052 .build();
13053 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013054 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013055 InputEventInjectionSync::WAIT_FOR_RESULT))
13056 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13057
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013058 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000013059 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013060}
13061
13062/**
13063 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
13064 * do not receive key events.
13065 */
13066TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013067 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013068 spy->setFocusable(false);
13069
13070 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013071 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013072 setFocusedWindow(window);
13073 window->consumeFocusEvent(true);
13074
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013076 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013077 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013078
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013079 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013080 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013081 window->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013082
13083 spy->assertNoEvents();
13084}
13085
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013086using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
13087
13088/**
13089 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
13090 * are currently sent to any other windows - including other spy windows - will also be cancelled.
13091 */
13092TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
13093 auto window = createForeground();
13094 auto spy1 = createSpy();
13095 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013096 mDispatcher->onWindowInfosChanged(
13097 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013098
13099 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013100 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13101 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013102 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13103 window->consumeMotionDown();
13104 spy1->consumeMotionDown();
13105 spy2->consumeMotionDown();
13106
13107 // Pilfer pointers from the second spy window.
13108 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
13109 spy2->assertNoEvents();
13110 spy1->consumeMotionCancel();
13111 window->consumeMotionCancel();
13112
13113 // The rest of the gesture should only be sent to the second spy window.
13114 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013115 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013116 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013117 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13118 spy2->consumeMotionMove();
13119 spy1->assertNoEvents();
13120 window->assertNoEvents();
13121}
13122
13123/**
13124 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
13125 * in the middle of the gesture.
13126 */
13127TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
13128 auto window = createForeground();
13129 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013130 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013131
13132 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013133 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13134 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013135 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013136 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13137 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013138
13139 window->releaseChannel();
13140
13141 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13142
13143 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013144 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13145 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013146 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013147 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013148}
13149
13150/**
13151 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
13152 * the spy, but not to any other windows.
13153 */
13154TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
13155 auto spy = createSpy();
13156 auto window = createForeground();
13157
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013158 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013159
13160 // First finger down on the window and the spy.
13161 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013162 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13163 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013164 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13165 spy->consumeMotionDown();
13166 window->consumeMotionDown();
13167
13168 // Spy window pilfers the pointers.
13169 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13170 window->consumeMotionCancel();
13171
13172 // Second finger down on the window and spy, but the window should not receive the pointer down.
13173 const MotionEvent secondFingerDownEvent =
13174 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013175 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013176 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013177 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13178 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013179 .build();
13180 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013181 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013182 InputEventInjectionSync::WAIT_FOR_RESULT))
13183 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13184
Harry Cutts33476232023-01-30 19:57:29 +000013185 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013186
13187 // Third finger goes down outside all windows, so injection should fail.
13188 const MotionEvent thirdFingerDownEvent =
13189 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013190 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013191 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013192 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13193 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
13194 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013195 .build();
13196 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013197 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013198 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080013199 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013200
13201 spy->assertNoEvents();
13202 window->assertNoEvents();
13203}
13204
13205/**
13206 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
13207 */
13208TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
13209 auto spy = createSpy();
13210 spy->setFrame(Rect(0, 0, 100, 100));
13211 auto window = createForeground();
13212 window->setFrame(Rect(0, 0, 200, 200));
13213
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013214 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013215
13216 // First finger down on the window only
13217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013218 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13219 ui::LogicalDisplayId::DEFAULT, {150, 150}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013220 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13221 window->consumeMotionDown();
13222
13223 // Second finger down on the spy and window
13224 const MotionEvent secondFingerDownEvent =
13225 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013226 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013227 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013228 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13229 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013230 .build();
13231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013232 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013233 InputEventInjectionSync::WAIT_FOR_RESULT))
13234 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13235 spy->consumeMotionDown();
13236 window->consumeMotionPointerDown(1);
13237
13238 // Third finger down on the spy and window
13239 const MotionEvent thirdFingerDownEvent =
13240 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013241 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013242 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013243 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13244 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
13245 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013246 .build();
13247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013248 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013249 InputEventInjectionSync::WAIT_FOR_RESULT))
13250 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13251 spy->consumeMotionPointerDown(1);
13252 window->consumeMotionPointerDown(2);
13253
13254 // Spy window pilfers the pointers.
13255 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +000013256 window->consumeMotionPointerUp(/*pointerIdx=*/2,
13257 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13258 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13259 WithPointerCount(3)));
13260 window->consumeMotionPointerUp(/*pointerIdx=*/1,
13261 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13262 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13263 WithPointerCount(2)));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013264
13265 spy->assertNoEvents();
13266 window->assertNoEvents();
13267}
13268
13269/**
13270 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
13271 * other windows should be canceled. If this results in the cancellation of all pointers for some
13272 * window, then that window should receive ACTION_CANCEL.
13273 */
13274TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
13275 auto spy = createSpy();
13276 spy->setFrame(Rect(0, 0, 100, 100));
13277 auto window = createForeground();
13278 window->setFrame(Rect(0, 0, 200, 200));
13279
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013280 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013281
13282 // First finger down on both spy and window
13283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013284 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13285 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013286 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13287 window->consumeMotionDown();
13288 spy->consumeMotionDown();
13289
13290 // Second finger down on the spy and window
13291 const MotionEvent secondFingerDownEvent =
13292 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013293 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013294 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013295 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13296 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013297 .build();
13298 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013299 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013300 InputEventInjectionSync::WAIT_FOR_RESULT))
13301 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13302 spy->consumeMotionPointerDown(1);
13303 window->consumeMotionPointerDown(1);
13304
13305 // Spy window pilfers the pointers.
13306 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13307 window->consumeMotionCancel();
13308
13309 spy->assertNoEvents();
13310 window->assertNoEvents();
13311}
13312
13313/**
13314 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
13315 * be sent to other windows
13316 */
13317TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
13318 auto spy = createSpy();
13319 spy->setFrame(Rect(0, 0, 100, 100));
13320 auto window = createForeground();
13321 window->setFrame(Rect(0, 0, 200, 200));
13322
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013323 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013324
13325 // First finger down on both window and spy
13326 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013327 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13328 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013329 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13330 window->consumeMotionDown();
13331 spy->consumeMotionDown();
13332
13333 // Spy window pilfers the pointers.
13334 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13335 window->consumeMotionCancel();
13336
13337 // Second finger down on the window only
13338 const MotionEvent secondFingerDownEvent =
13339 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013340 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013341 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013342 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13343 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013344 .build();
13345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013346 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013347 InputEventInjectionSync::WAIT_FOR_RESULT))
13348 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13349 window->consumeMotionDown();
13350 window->assertNoEvents();
13351
13352 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
13353 spy->consumeMotionMove();
13354 spy->assertNoEvents();
13355}
13356
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013357/**
13358 * A window on the left and a window on the right. Also, a spy window that's above all of the
13359 * windows, and spanning both left and right windows.
13360 * Send simultaneous motion streams from two different devices, one to the left window, and another
13361 * to the right window.
13362 * Pilfer from spy window.
13363 * Check that the pilfering only affects the pointers that are actually being received by the spy.
13364 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013365TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer_legacy) {
13366 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013367 sp<FakeWindowHandle> spy = createSpy();
13368 spy->setFrame(Rect(0, 0, 200, 200));
13369 sp<FakeWindowHandle> leftWindow = createForeground();
13370 leftWindow->setFrame(Rect(0, 0, 100, 100));
13371
13372 sp<FakeWindowHandle> rightWindow = createForeground();
13373 rightWindow->setFrame(Rect(100, 0, 200, 100));
13374
13375 constexpr int32_t stylusDeviceId = 1;
13376 constexpr int32_t touchDeviceId = 2;
13377
13378 mDispatcher->onWindowInfosChanged(
13379 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13380
13381 // Stylus down on left window and spy
13382 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13383 .deviceId(stylusDeviceId)
13384 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13385 .build());
13386 leftWindow->consumeMotionEvent(
13387 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13388 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13389
13390 // Finger down on right window and spy - but spy already has stylus
13391 mDispatcher->notifyMotion(
13392 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13393 .deviceId(touchDeviceId)
13394 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13395 .build());
13396 rightWindow->consumeMotionEvent(
13397 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013398 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013399
13400 // Act: pilfer from spy. Spy is currently receiving touch events.
13401 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013402 leftWindow->consumeMotionEvent(
13403 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013404 rightWindow->consumeMotionEvent(
13405 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13406
13407 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
13408 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13409 .deviceId(stylusDeviceId)
13410 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13411 .build());
13412 mDispatcher->notifyMotion(
13413 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13414 .deviceId(touchDeviceId)
13415 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13416 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013417 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013418
13419 spy->assertNoEvents();
13420 leftWindow->assertNoEvents();
13421 rightWindow->assertNoEvents();
13422}
13423
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013424/**
13425 * A window on the left and a window on the right. Also, a spy window that's above all of the
13426 * windows, and spanning both left and right windows.
13427 * Send simultaneous motion streams from two different devices, one to the left window, and another
13428 * to the right window.
13429 * Pilfer from spy window.
13430 * Check that the pilfering affects all of the pointers that are actually being received by the spy.
13431 * The spy should receive both the touch and the stylus events after pilfer.
13432 */
13433TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
13434 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13435 sp<FakeWindowHandle> spy = createSpy();
13436 spy->setFrame(Rect(0, 0, 200, 200));
13437 sp<FakeWindowHandle> leftWindow = createForeground();
13438 leftWindow->setFrame(Rect(0, 0, 100, 100));
13439
13440 sp<FakeWindowHandle> rightWindow = createForeground();
13441 rightWindow->setFrame(Rect(100, 0, 200, 100));
13442
13443 constexpr int32_t stylusDeviceId = 1;
13444 constexpr int32_t touchDeviceId = 2;
13445
13446 mDispatcher->onWindowInfosChanged(
13447 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13448
13449 // Stylus down on left window and spy
13450 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13451 .deviceId(stylusDeviceId)
13452 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13453 .build());
13454 leftWindow->consumeMotionEvent(
13455 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13456 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13457
13458 // Finger down on right window and spy
13459 mDispatcher->notifyMotion(
13460 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13461 .deviceId(touchDeviceId)
13462 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13463 .build());
13464 rightWindow->consumeMotionEvent(
13465 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13466 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13467
13468 // Act: pilfer from spy. Spy is currently receiving touch events.
13469 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13470 leftWindow->consumeMotionEvent(
13471 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
13472 rightWindow->consumeMotionEvent(
13473 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13474
13475 // Continue movements from both stylus and touch. Touch and stylus will be delivered to spy
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013476 // Instead of sending the two MOVE events for each input device together, and then receiving
13477 // them both, process them one at at time. InputConsumer is always in the batching mode, which
13478 // means that the two MOVE events will be initially put into a batch. Once the events are
13479 // batched, the 'consume' call may result in any of the MOVE events to be sent first (depending
13480 // on the implementation of InputConsumer), which would mean that the order of the received
13481 // events could be different depending on whether there are 1 or 2 events pending in the
13482 // InputChannel at the time the test calls 'consume'. To make assertions simpler here, and to
13483 // avoid this confusing behaviour, send and receive each MOVE event separately.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013484 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13485 .deviceId(stylusDeviceId)
13486 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13487 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013488 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013489 mDispatcher->notifyMotion(
13490 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13491 .deviceId(touchDeviceId)
13492 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13493 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013494 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013495
13496 spy->assertNoEvents();
13497 leftWindow->assertNoEvents();
13498 rightWindow->assertNoEvents();
13499}
13500
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000013501TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
13502 auto window = createForeground();
13503 auto spy = createSpy();
13504 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13505
13506 mDispatcher->notifyMotion(
13507 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
13508 .deviceId(1)
13509 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
13510 .build());
13511 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13512 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13513
13514 // Pilfer pointers from the spy window should fail.
13515 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
13516 spy->assertNoEvents();
13517 window->assertNoEvents();
13518}
13519
Prabir Pradhand65552b2021-10-07 11:23:50 -070013520class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
13521public:
13522 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
13523 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13524 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013525 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
13526 "Stylus interceptor window",
13527 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013528 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013529 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013530 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013531 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013532 overlay->setTrustedOverlay(true);
13533
13534 std::shared_ptr<FakeApplicationHandle> application =
13535 std::make_shared<FakeApplicationHandle>();
13536 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013537 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013538 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013539 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013540 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013541
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013542 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013543 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013544 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013545 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013546 return {std::move(overlay), std::move(window)};
13547 }
13548
13549 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000013550 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070013551 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013552 ui::LogicalDisplayId::DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070013553 }
13554
13555 void sendStylusEvent(int32_t action) {
13556 NotifyMotionArgs motionArgs =
13557 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013558 ui::LogicalDisplayId::DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013559 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000013560 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013561 }
13562};
13563
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013564using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
13565
13566TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070013567 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013568 ScopedSilentDeath _silentDeath;
13569
Prabir Pradhand65552b2021-10-07 11:23:50 -070013570 auto [overlay, window] = setupStylusOverlayScenario();
13571 overlay->setTrustedOverlay(false);
13572 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013573 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
13574 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070013575 ".* not a trusted overlay");
13576}
13577
13578TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
13579 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013580 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013581
13582 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13583 overlay->consumeMotionDown();
13584 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13585 overlay->consumeMotionUp();
13586
13587 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13588 window->consumeMotionDown();
13589 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13590 window->consumeMotionUp();
13591
13592 overlay->assertNoEvents();
13593 window->assertNoEvents();
13594}
13595
13596TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
13597 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013598 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013599 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013600
13601 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13602 overlay->consumeMotionDown();
13603 window->consumeMotionDown();
13604 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13605 overlay->consumeMotionUp();
13606 window->consumeMotionUp();
13607
13608 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13609 window->consumeMotionDown();
13610 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13611 window->consumeMotionUp();
13612
13613 overlay->assertNoEvents();
13614 window->assertNoEvents();
13615}
13616
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013617/**
13618 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
13619 * The scenario is as follows:
13620 * - The stylus interceptor overlay is configured as a spy window.
13621 * - The stylus interceptor spy receives the start of a new stylus gesture.
13622 * - It pilfers pointers and then configures itself to no longer be a spy.
13623 * - The stylus interceptor continues to receive the rest of the gesture.
13624 */
13625TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
13626 auto [overlay, window] = setupStylusOverlayScenario();
13627 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013628 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013629
13630 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13631 overlay->consumeMotionDown();
13632 window->consumeMotionDown();
13633
13634 // The interceptor pilfers the pointers.
13635 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
13636 window->consumeMotionCancel();
13637
13638 // The interceptor configures itself so that it is no longer a spy.
13639 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013640 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013641
13642 // It continues to receive the rest of the stylus gesture.
13643 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
13644 overlay->consumeMotionMove();
13645 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13646 overlay->consumeMotionUp();
13647
13648 window->assertNoEvents();
13649}
13650
Prabir Pradhan5735a322022-04-11 17:23:34 +000013651struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013652 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013653 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000013654 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
13655 std::unique_ptr<InputDispatcher>& mDispatcher;
13656
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013657 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000013658 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
13659
13660 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013661 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013662 ui::LogicalDisplayId::DEFAULT, {100, 200},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013663 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
13664 AMOTION_EVENT_INVALID_CURSOR_POSITION},
13665 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
13666 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
13667 }
13668
13669 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Linnan Li13bf76a2024-05-05 19:18:02 +080013670 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013671 ui::LogicalDisplayId::INVALID,
Prabir Pradhan5735a322022-04-11 17:23:34 +000013672 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000013673 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013674 mPolicyFlags);
13675 }
13676
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013677 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000013678 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13679 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013680 sp<FakeWindowHandle> window =
13681 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, name,
13682 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013683 window->setOwnerInfo(mPid, mUid);
13684 return window;
13685 }
13686};
13687
13688using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
13689
13690TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013691 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013692 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013693 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013694
13695 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13696 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13697 window->consumeMotionDown();
13698
13699 setFocusedWindow(window);
13700 window->consumeFocusEvent(true);
13701
13702 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13703 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013704 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013705}
13706
13707TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013708 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013709 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013710 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013711
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013712 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013713 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13714 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13715
13716 setFocusedWindow(window);
13717 window->consumeFocusEvent(true);
13718
13719 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13720 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
13721 window->assertNoEvents();
13722}
13723
13724TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013725 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013726 auto window = owner.createWindow("Owned window");
13727 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013728 spy->setSpy(true);
13729 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013730 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013731
13732 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13733 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13734 spy->consumeMotionDown();
13735 window->consumeMotionDown();
13736}
13737
13738TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013739 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013740 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013741
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013742 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013743 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013744 randosSpy->setSpy(true);
13745 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013746 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013747
13748 // The event is targeted at owner's window, so injection should succeed, but the spy should
13749 // not receive the event.
13750 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13751 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13752 randosSpy->assertNoEvents();
13753 window->consumeMotionDown();
13754}
13755
13756TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013757 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013758 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013759
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013760 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013761 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013762 randosSpy->setSpy(true);
13763 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013764 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013765
13766 // A user that has injection permission can inject into any window.
13767 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013768 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013769 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan5735a322022-04-11 17:23:34 +000013770 randosSpy->consumeMotionDown();
13771 window->consumeMotionDown();
13772
13773 setFocusedWindow(randosSpy);
13774 randosSpy->consumeFocusEvent(true);
13775
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013776 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013777 randosSpy->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013778 window->assertNoEvents();
13779}
13780
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013781TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013782 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013783 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013784
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013785 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013786 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013787 randosWindow->setFrame(Rect{-10, -10, -5, -5});
13788 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013789 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013790
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013791 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000013792 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13793 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13794 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013795 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000013796}
13797
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013798using InputDispatcherPointerInWindowTest = InputDispatcherTest;
13799
13800TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
13801 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13802
13803 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013804 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013805 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013806 sp<FakeWindowHandle> right =
13807 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13808 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013809 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013810 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13811 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013812 spy->setFrame(Rect(0, 0, 200, 100));
13813 spy->setTrustedOverlay(true);
13814 spy->setSpy(true);
13815
13816 mDispatcher->onWindowInfosChanged(
13817 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13818
13819 // Hover into the left window.
13820 mDispatcher->notifyMotion(
13821 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
13822 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
13823 .build());
13824
13825 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13826 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13827
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013828 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13829 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013830 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013831 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13832 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013833 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013834 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13835 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013836 /*pointerId=*/0));
13837
13838 // Hover move to the right window.
13839 mDispatcher->notifyMotion(
13840 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
13841 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13842 .build());
13843
13844 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13845 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13846 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
13847
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013848 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13849 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013850 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013851 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13852 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013853 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013854 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13855 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013856 /*pointerId=*/0));
13857
13858 // Stop hovering.
13859 mDispatcher->notifyMotion(
13860 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
13861 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13862 .build());
13863
13864 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13865 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13866
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013867 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13868 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013869 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013870 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13871 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013872 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013873 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13874 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013875 /*pointerId=*/0));
13876}
13877
13878TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
13879 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13880
13881 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013882 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013883 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013884 sp<FakeWindowHandle> right =
13885 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13886 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013887 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013888 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13889 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013890 spy->setFrame(Rect(0, 0, 200, 100));
13891 spy->setTrustedOverlay(true);
13892 spy->setSpy(true);
13893
13894 mDispatcher->onWindowInfosChanged(
13895 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13896
13897 // First pointer down on left window.
13898 mDispatcher->notifyMotion(
13899 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13900 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13901 .build());
13902
13903 left->consumeMotionDown();
13904 spy->consumeMotionDown();
13905
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013906 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13907 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013908 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013909 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13910 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013911 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013912 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13913 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013914 /*pointerId=*/0));
13915
13916 // Second pointer down on right window.
13917 mDispatcher->notifyMotion(
13918 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13919 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13920 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13921 .build());
13922
13923 left->consumeMotionMove();
13924 right->consumeMotionDown();
13925 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
13926
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013927 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13928 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013929 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013930 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13931 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013932 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013933 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13934 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013935 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013936 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13937 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013938 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013939 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13940 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013941 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013942 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13943 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013944 /*pointerId=*/1));
13945
13946 // Second pointer up.
13947 mDispatcher->notifyMotion(
13948 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
13949 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13950 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13951 .build());
13952
13953 left->consumeMotionMove();
13954 right->consumeMotionUp();
13955 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
13956
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013957 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13958 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013959 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013960 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13961 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013962 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013963 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13964 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013965 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013966 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13967 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013968 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013969 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13970 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013971 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013972 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13973 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013974 /*pointerId=*/1));
13975
13976 // First pointer up.
13977 mDispatcher->notifyMotion(
13978 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
13979 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13980 .build());
13981
13982 left->consumeMotionUp();
13983 spy->consumeMotionUp();
13984
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013985 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13986 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013987 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013988 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13989 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013990 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013991 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13992 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013993 /*pointerId=*/0));
13994}
13995
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013996TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse_legacy) {
13997 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013998 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13999
14000 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014001 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014002 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014003 sp<FakeWindowHandle> right =
14004 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14005 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014006 right->setFrame(Rect(100, 0, 200, 100));
14007
14008 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
14009
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014010 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14011 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014012 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014013 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14014 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014015 /*pointerId=*/0));
14016
14017 // Hover move into the window.
14018 mDispatcher->notifyMotion(
14019 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14020 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
14021 .rawXCursorPosition(50)
14022 .rawYCursorPosition(50)
14023 .deviceId(DEVICE_ID)
14024 .build());
14025
14026 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14027
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014028 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14029 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014030 /*pointerId=*/0));
14031
14032 // Move the mouse with another device. This cancels the hovering pointer from the first device.
14033 mDispatcher->notifyMotion(
14034 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14035 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
14036 .rawXCursorPosition(51)
14037 .rawYCursorPosition(50)
14038 .deviceId(SECOND_DEVICE_ID)
14039 .build());
14040
14041 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14042 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14043
14044 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
14045 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014046 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14047 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014048 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014049 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014050 SECOND_DEVICE_ID,
14051 /*pointerId=*/0));
14052
14053 // Move the mouse outside the window. Document the current behavior, where the window does not
14054 // receive HOVER_EXIT even though the mouse left the window.
14055 mDispatcher->notifyMotion(
14056 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14057 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
14058 .rawXCursorPosition(150)
14059 .rawYCursorPosition(50)
14060 .deviceId(SECOND_DEVICE_ID)
14061 .build());
14062
14063 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14064 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014065 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14066 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014067 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014068 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014069 SECOND_DEVICE_ID,
14070 /*pointerId=*/0));
14071}
14072
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014073/**
14074 * TODO(b/313689709) - correctly support multiple mouse devices, because they should be controlling
14075 * the same cursor, and therefore have a shared motion event stream.
14076 */
14077TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
14078 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
14079 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14080
14081 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014082 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014083 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014084 sp<FakeWindowHandle> right =
14085 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14086 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014087 right->setFrame(Rect(100, 0, 200, 100));
14088
14089 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
14090
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014091 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14092 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014093 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014094 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14095 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014096 /*pointerId=*/0));
14097
14098 // Hover move into the window.
14099 mDispatcher->notifyMotion(
14100 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14101 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
14102 .rawXCursorPosition(50)
14103 .rawYCursorPosition(50)
14104 .deviceId(DEVICE_ID)
14105 .build());
14106
14107 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14108
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014109 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14110 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014111 /*pointerId=*/0));
14112
14113 // Move the mouse with another device
14114 mDispatcher->notifyMotion(
14115 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14116 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
14117 .rawXCursorPosition(51)
14118 .rawYCursorPosition(50)
14119 .deviceId(SECOND_DEVICE_ID)
14120 .build());
14121 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14122
14123 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
14124 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014125 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14126 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014127 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014128 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014129 SECOND_DEVICE_ID,
14130 /*pointerId=*/0));
14131
14132 // Move the mouse outside the window. Document the current behavior, where the window does not
14133 // receive HOVER_EXIT even though the mouse left the window.
14134 mDispatcher->notifyMotion(
14135 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14136 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
14137 .rawXCursorPosition(150)
14138 .rawYCursorPosition(50)
14139 .deviceId(SECOND_DEVICE_ID)
14140 .build());
14141
14142 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014143 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14144 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014145 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014146 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014147 SECOND_DEVICE_ID,
14148 /*pointerId=*/0));
14149}
14150
Arpit Singhb65e2bd2024-06-03 09:48:16 +000014151TEST_F(InputDispatcherTest, FocusedDisplayChangeIsNotified) {
14152 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
14153 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
14154}
14155
Garfield Tane84e6f92019-08-29 17:28:41 -070014156} // namespace android::inputdispatcher