blob: f066b031f3253d2554feaea2f7451dbb0f3b2de4 [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) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07004171 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakouac42d242024-06-28 10:43:53 -07004172 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4173 sp<FakeWindowHandle> window1 =
4174 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4175 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4176 window1->setPreventSplitting(true);
4177
4178 sp<FakeWindowHandle> window2 =
4179 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4180 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4181
4182 mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4183
4184 // Touch down on the first window
4185 NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4186 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4187 .build();
4188 mDispatcher->notifyMotion(downArgs);
4189
4190 window1->consumeMotionEvent(
4191 AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4192
4193 // Second window is added
4194 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4195
4196 // Now touch down on the window with another pointer
4197 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4198 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4199 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4200 .downTime(downArgs.downTime)
4201 .build());
4202 window1->consumeMotionPointerDown(1, AllOf(WithDownTime(downArgs.downTime)));
4203
4204 // Finish the gesture
4205 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4206 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4207 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4208 .downTime(downArgs.downTime)
4209 .build());
4210 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4211 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4212 .downTime(downArgs.downTime)
4213 .build());
4214 window1->consumeMotionPointerUp(1, AllOf(WithDownTime(downArgs.downTime)));
4215 window1->consumeMotionEvent(
4216 AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4217 window2->assertNoEvents();
4218}
4219
4220/**
4221 * When splitting touch events, the downTime should be adjusted such that the downTime corresponds
4222 * to the event time of the first ACTION_DOWN sent to the new window.
4223 * If a new window that does not support split appears on the screen and gets touched with the
4224 * second finger, it should not get any events because it doesn't want split touches. At the same
4225 * time, the first window should not get the pointer_down event because it supports split touches
4226 * (and the touch occurred outside of the bounds of window1).
4227 */
4228TEST_F(InputDispatcherTest, SplitTouchesDropsEventForNonSplittableSecondWindow) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07004229 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakouac42d242024-06-28 10:43:53 -07004230 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4231 sp<FakeWindowHandle> window1 =
4232 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
4233 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4234
4235 sp<FakeWindowHandle> window2 =
4236 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
4237 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4238
4239 mDispatcher->onWindowInfosChanged({{*window1->getInfo()}, {}, 0, 0});
4240
4241 // Touch down on the first window
4242 NotifyMotionArgs downArgs = MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4243 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4244 .build();
4245 mDispatcher->notifyMotion(downArgs);
4246
4247 window1->consumeMotionEvent(
4248 AllOf(WithMotionAction(ACTION_DOWN), WithDownTime(downArgs.downTime)));
4249
4250 // Second window is added
4251 window2->setPreventSplitting(true);
4252 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
4253
4254 // Now touch down on the window with another pointer
4255 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4256 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4257 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4258 .downTime(downArgs.downTime)
4259 .build());
4260 // Event is dropped because window2 doesn't support split touch, and window1 does.
4261
4262 // Complete the gesture
4263 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4264 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4265 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
4266 .downTime(downArgs.downTime)
4267 .build());
4268 // A redundant MOVE event is generated that doesn't carry any new information
4269 window1->consumeMotionEvent(
4270 AllOf(WithMotionAction(ACTION_MOVE), WithDownTime(downArgs.downTime)));
4271 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4272 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4273 .downTime(downArgs.downTime)
4274 .build());
4275
4276 window1->consumeMotionEvent(
4277 AllOf(WithMotionAction(ACTION_UP), WithDownTime(downArgs.downTime)));
4278 window1->assertNoEvents();
4279 window2->assertNoEvents();
4280}
4281
Garfield Tandf26e862020-07-01 20:18:19 -07004282TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004283 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004284 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4285 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004286 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004287 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4288 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004289 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004290
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004291 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004292
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004293 mDispatcher->onWindowInfosChanged(
4294 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004295
4296 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004297 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004298 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004299 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4300 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004301 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004302 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004303 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004304
4305 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004307 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004308 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4309 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004310 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004311 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004312 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4313 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004314
4315 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004316 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004317 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004318 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4319 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004320 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004321 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004322 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4323 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004324
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004325 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004326 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004327 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4328 AINPUT_SOURCE_MOUSE)
4329 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4330 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004331 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004332 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004333 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004334
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004335 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004336 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004337 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4338 AINPUT_SOURCE_MOUSE)
4339 .buttonState(0)
4340 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004341 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004342 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004343 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004344
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004345 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004346 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004347 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4348 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004349 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004350 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004351 windowLeft->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004352
4353 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004355 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004356 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4357 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004358 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004359 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004360 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004361
4362 // No more events
4363 windowLeft->assertNoEvents();
4364 windowRight->assertNoEvents();
4365}
4366
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004367/**
4368 * Put two fingers down (and don't release them) and click the mouse button.
4369 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4370 * currently active gesture should be canceled, and the new one should proceed.
4371 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004372TEST_F(InputDispatcherTest, TwoPointersDownMouseClick_legacy) {
4373 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004375 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4376 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004377 window->setFrame(Rect(0, 0, 600, 800));
4378
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004379 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004380
4381 const int32_t touchDeviceId = 4;
4382 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004383
4384 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004385 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4386 .deviceId(touchDeviceId)
4387 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4388 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004389
Prabir Pradhan678438e2023-04-13 19:32:51 +00004390 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4391 .deviceId(touchDeviceId)
4392 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4393 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4394 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004395 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4396 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4397
4398 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004399 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4400 .deviceId(mouseDeviceId)
4401 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4402 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4403 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004404 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4405 WithPointerCount(2u)));
4406 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4407
Prabir Pradhan678438e2023-04-13 19:32:51 +00004408 mDispatcher->notifyMotion(
4409 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4410 .deviceId(mouseDeviceId)
4411 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4412 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4413 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4414 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004415 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4416
4417 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4418 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004419 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4420 .deviceId(touchDeviceId)
4421 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4422 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4423 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004424 window->assertNoEvents();
4425}
4426
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004427/**
4428 * Put two fingers down (and don't release them) and click the mouse button.
4429 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4430 * currently active gesture should not be canceled, and the new one should proceed in parallel.
4431 */
4432TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4433 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4434 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004435 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4436 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004437 window->setFrame(Rect(0, 0, 600, 800));
4438
4439 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4440
4441 const int32_t touchDeviceId = 4;
4442 const int32_t mouseDeviceId = 6;
4443
4444 // Two pointers down
4445 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4446 .deviceId(touchDeviceId)
4447 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4448 .build());
4449
4450 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4451 .deviceId(touchDeviceId)
4452 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4453 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4454 .build());
4455 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4456 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4457
4458 // Send a series of mouse events for a mouse click
4459 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4460 .deviceId(mouseDeviceId)
4461 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4462 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4463 .build());
4464 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4465
4466 mDispatcher->notifyMotion(
4467 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4468 .deviceId(mouseDeviceId)
4469 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4470 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4471 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4472 .build());
4473 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4474
4475 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4476 // already active gesture, it should be sent normally.
4477 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4478 .deviceId(touchDeviceId)
4479 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4480 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4481 .build());
4482 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4483 window->assertNoEvents();
4484}
4485
Siarhei Vishniakou07cdda92024-07-01 16:45:08 -07004486/**
4487 * A spy window sits above a window with NO_INPUT_CHANNEL. Ensure that the spy receives events even
4488 * though the window underneath should not get any events.
4489 */
4490TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowSinglePointer) {
4491 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4492
4493 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4494 ui::LogicalDisplayId::DEFAULT);
4495 spyWindow->setFrame(Rect(0, 0, 100, 100));
4496 spyWindow->setTrustedOverlay(true);
4497 spyWindow->setPreventSplitting(true);
4498 spyWindow->setSpy(true);
4499 // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4500 sp<FakeWindowHandle> inputSinkWindow =
4501 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4502 ui::LogicalDisplayId::DEFAULT);
4503 inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
4504 inputSinkWindow->setTrustedOverlay(true);
4505 inputSinkWindow->setPreventSplitting(true);
4506 inputSinkWindow->setNoInputChannel(true);
4507
4508 mDispatcher->onWindowInfosChanged(
4509 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo()}, {}, 0, 0});
4510
4511 // Tap the spy window
4512 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4513 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(51))
4514 .build());
4515 mDispatcher->notifyMotion(
4516 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4517 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4518 .build());
4519
4520 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4521 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP)));
4522 inputSinkWindow->assertNoEvents();
4523}
4524
4525/**
4526 * A spy window sits above a window with NO_INPUT_CHANNEL. Ensure that the spy receives events even
4527 * though the window underneath should not get any events.
4528 * Same test as above, but with two pointers touching instead of one.
4529 */
4530TEST_F(InputDispatcherTest, NonSplittableSpyAboveNoInputChannelWindowTwoPointers) {
4531 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4532
4533 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4534 ui::LogicalDisplayId::DEFAULT);
4535 spyWindow->setFrame(Rect(0, 0, 100, 100));
4536 spyWindow->setTrustedOverlay(true);
4537 spyWindow->setPreventSplitting(true);
4538 spyWindow->setSpy(true);
4539 // Another window below spy that would have both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4540 sp<FakeWindowHandle> inputSinkWindow =
4541 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4542 ui::LogicalDisplayId::DEFAULT);
4543 inputSinkWindow->setFrame(Rect(0, 0, 100, 100));
4544 inputSinkWindow->setTrustedOverlay(true);
4545 inputSinkWindow->setPreventSplitting(true);
4546 inputSinkWindow->setNoInputChannel(true);
4547
4548 mDispatcher->onWindowInfosChanged(
4549 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo()}, {}, 0, 0});
4550
4551 // Both fingers land into the spy window
4552 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4553 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(51))
4554 .build());
4555 mDispatcher->notifyMotion(
4556 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4557 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4558 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(11))
4559 .build());
4560 mDispatcher->notifyMotion(
4561 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
4562 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4563 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(11))
4564 .build());
4565 mDispatcher->notifyMotion(
4566 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4567 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(51))
4568 .build());
4569
4570 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4571 spyWindow->consumeMotionPointerDown(1, WithPointerCount(2));
4572 spyWindow->consumeMotionPointerUp(1, WithPointerCount(2));
4573 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP)));
4574 inputSinkWindow->assertNoEvents();
4575}
4576
4577/** Check the behaviour for cases where input sink prevents or doesn't prevent splitting. */
4578class SpyThatPreventsSplittingWithApplicationFixture : public InputDispatcherTest,
4579 public ::testing::WithParamInterface<bool> {
4580};
4581
4582/**
4583 * Three windows:
4584 * - An application window (app window)
4585 * - A spy window that does not overlap the app window. Has PREVENT_SPLITTING flag
4586 * - A window below the spy that has NO_INPUT_CHANNEL (call it 'inputSink')
4587 *
4588 * The spy window is side-by-side with the app window. The inputSink is below the spy.
4589 * We first touch the area outside of the appWindow, but inside spyWindow.
4590 * Only the SPY window should get the DOWN event.
4591 * The spy pilfers after receiving the first DOWN event.
4592 * Next, we touch the app window.
4593 * The spy should receive POINTER_DOWN(1) (since spy is preventing splits).
4594 * Also, since the spy is already pilfering the first pointer, it will be sent the remaining new
4595 * pointers automatically, as well.
4596 * Next, the first pointer (from the spy) is lifted.
4597 * Spy should get POINTER_UP(0).
4598 * This event should not go to the app because the app never received this pointer to begin with.
4599 * Now, lift the remaining pointer and check that the spy receives UP event.
4600 *
4601 * Finally, send a new ACTION_DOWN event to the spy and check that it's received.
4602 * This test attempts to reproduce a crash in the dispatcher.
4603 */
4604TEST_P(SpyThatPreventsSplittingWithApplicationFixture, SpyThatPreventsSplittingWithApplication) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07004605 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakou07cdda92024-07-01 16:45:08 -07004606 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4607
4608 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4609 ui::LogicalDisplayId::DEFAULT);
4610 spyWindow->setFrame(Rect(100, 100, 200, 200));
4611 spyWindow->setTrustedOverlay(true);
4612 spyWindow->setPreventSplitting(true);
4613 spyWindow->setSpy(true);
4614 // Another window below spy that has both NO_INPUT_CHANNEL and PREVENT_SPLITTING
4615 sp<FakeWindowHandle> inputSinkWindow =
4616 sp<FakeWindowHandle>::make(application, mDispatcher, "Input sink below spy",
4617 ui::LogicalDisplayId::DEFAULT);
4618 inputSinkWindow->setFrame(Rect(100, 100, 200, 200)); // directly below the spy
4619 inputSinkWindow->setTrustedOverlay(true);
4620 inputSinkWindow->setPreventSplitting(GetParam());
4621 inputSinkWindow->setNoInputChannel(true);
4622
4623 sp<FakeWindowHandle> appWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "App",
4624 ui::LogicalDisplayId::DEFAULT);
4625 appWindow->setFrame(Rect(0, 0, 100, 100));
4626
4627 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
4628 mDispatcher->onWindowInfosChanged(
4629 {{*spyWindow->getInfo(), *inputSinkWindow->getInfo(), *appWindow->getInfo()},
4630 {},
4631 0,
4632 0});
4633
4634 // First finger lands outside of the appWindow, but inside of the spy window
4635 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4636 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
4637 .build());
4638 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4639
4640 mDispatcher->pilferPointers(spyWindow->getToken());
4641
4642 // Second finger lands in the app, and goes to the spy window. It doesn't go to the app because
4643 // the spy is already pilfering the first pointer, and this automatically grants the remaining
4644 // new pointers to the spy, as well.
4645 mDispatcher->notifyMotion(
4646 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4647 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
4648 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4649 .build());
4650
4651 spyWindow->consumeMotionPointerDown(1, WithPointerCount(2));
4652
4653 // Now lift up the first pointer
4654 mDispatcher->notifyMotion(
4655 MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
4656 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
4657 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4658 .build());
4659 spyWindow->consumeMotionPointerUp(0, WithPointerCount(2));
4660
4661 // And lift the remaining pointer!
4662 mDispatcher->notifyMotion(
4663 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4664 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
4665 .build());
4666 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithPointerCount(1)));
4667
4668 // Now send a new DOWN, which should again go to spy.
4669 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4670 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
4671 .build());
4672 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4673 // The app window doesn't get any events this entire time because the spy received the events
4674 // first and pilfered, which makes all new pointers go to it as well.
4675 appWindow->assertNoEvents();
4676}
4677
4678// Behaviour should be the same regardless of whether inputSink supports splitting.
4679INSTANTIATE_TEST_SUITE_P(SpyThatPreventsSplittingWithApplication,
4680 SpyThatPreventsSplittingWithApplicationFixture, testing::Bool());
4681
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004682TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4683 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4684
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004685 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4686 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004687 spyWindow->setFrame(Rect(0, 0, 600, 800));
4688 spyWindow->setTrustedOverlay(true);
4689 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004690 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4691 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004692 window->setFrame(Rect(0, 0, 600, 800));
4693
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004694 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004695 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004696
4697 // Send mouse cursor to the window
4698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004699 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004700 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4701 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004702 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004703 .build()));
4704
4705 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4706 WithSource(AINPUT_SOURCE_MOUSE)));
4707 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4708 WithSource(AINPUT_SOURCE_MOUSE)));
4709
4710 window->assertNoEvents();
4711 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004712}
4713
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004714TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows_legacy) {
4715 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004716 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4717
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004718 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4719 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004720 spyWindow->setFrame(Rect(0, 0, 600, 800));
4721 spyWindow->setTrustedOverlay(true);
4722 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004723 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4724 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004725 window->setFrame(Rect(0, 0, 600, 800));
4726
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004727 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004728 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004729
4730 // Send mouse cursor to the window
4731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004732 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004733 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4734 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004735 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004736 .build()));
4737
4738 // Move mouse cursor
4739 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004740 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004741 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4742 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004743 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004744 .build()));
4745
4746 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4747 WithSource(AINPUT_SOURCE_MOUSE)));
4748 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4749 WithSource(AINPUT_SOURCE_MOUSE)));
4750 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4751 WithSource(AINPUT_SOURCE_MOUSE)));
4752 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4753 WithSource(AINPUT_SOURCE_MOUSE)));
4754 // Touch down on the window
4755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004756 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004757 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4758 AINPUT_SOURCE_TOUCHSCREEN)
4759 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004760 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004761 .build()));
4762 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4763 WithSource(AINPUT_SOURCE_MOUSE)));
4764 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4765 WithSource(AINPUT_SOURCE_MOUSE)));
4766 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4767 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4768 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4769 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4770
4771 // pilfer the motion, retaining the gesture on the spy window.
4772 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4773 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4774 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4775
4776 // Touch UP on the window
4777 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004778 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004779 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4780 AINPUT_SOURCE_TOUCHSCREEN)
4781 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004782 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004783 .build()));
4784 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4785 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4786
4787 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4788 // to send a new gesture. It should again go to both windows (spy and the window below), just
4789 // like the first gesture did, before pilfering. The window configuration has not changed.
4790
4791 // One more tap - DOWN
4792 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004793 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004794 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4795 AINPUT_SOURCE_TOUCHSCREEN)
4796 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004797 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004798 .build()));
4799 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4800 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4801 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4802 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4803
4804 // Touch UP on the window
4805 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004806 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004807 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4808 AINPUT_SOURCE_TOUCHSCREEN)
4809 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004810 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004811 .build()));
4812 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4813 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4814 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4815 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4816
4817 window->assertNoEvents();
4818 spyWindow->assertNoEvents();
4819}
4820
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004821TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4822 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4823 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4824
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004825 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4826 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004827 spyWindow->setFrame(Rect(0, 0, 600, 800));
4828 spyWindow->setTrustedOverlay(true);
4829 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004830 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4831 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004832 window->setFrame(Rect(0, 0, 600, 800));
4833
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004834 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004835 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4836
4837 // Send mouse cursor to the window
4838 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4839 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4840 .build());
4841
4842 // Move mouse cursor
4843 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4844 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4845 .build());
4846
4847 window->consumeMotionEvent(
4848 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4849 spyWindow->consumeMotionEvent(
4850 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4851 window->consumeMotionEvent(
4852 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4853 spyWindow->consumeMotionEvent(
4854 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4855 // Touch down on the window
4856 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4857 .deviceId(SECOND_DEVICE_ID)
4858 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4859 .build());
4860 window->consumeMotionEvent(
4861 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4862 spyWindow->consumeMotionEvent(
4863 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4864
4865 // pilfer the motion, retaining the gesture on the spy window.
4866 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4867 window->consumeMotionEvent(
4868 AllOf(WithMotionAction(ACTION_CANCEL), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4869 // Mouse hover is not pilfered
4870
4871 // Touch UP on the window
4872 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4873 .deviceId(SECOND_DEVICE_ID)
4874 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4875 .build());
4876 spyWindow->consumeMotionEvent(
4877 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4878
4879 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4880 // to send a new gesture. It should again go to both windows (spy and the window below), just
4881 // like the first gesture did, before pilfering. The window configuration has not changed.
4882
4883 // One more tap - DOWN
4884 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4885 .deviceId(SECOND_DEVICE_ID)
4886 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4887 .build());
4888 window->consumeMotionEvent(
4889 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4890 spyWindow->consumeMotionEvent(
4891 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4892
4893 // Touch UP on the window
4894 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4895 .deviceId(SECOND_DEVICE_ID)
4896 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4897 .build());
4898 window->consumeMotionEvent(
4899 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4900 spyWindow->consumeMotionEvent(
4901 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4902
4903 // Mouse movement continues normally as well
4904 // Move mouse cursor
4905 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4906 .pointer(PointerBuilder(0, ToolType::MOUSE).x(120).y(130))
4907 .build());
4908 window->consumeMotionEvent(
4909 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4910 spyWindow->consumeMotionEvent(
4911 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4912
4913 window->assertNoEvents();
4914 spyWindow->assertNoEvents();
4915}
4916
Garfield Tandf26e862020-07-01 20:18:19 -07004917// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4918// directly in this test.
4919TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004920 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004921 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4922 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004923 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004924
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004925 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004926
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004927 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004928
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004929 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004930 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004931 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4932 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004933 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004934 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004935 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004936 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004937 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004938 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004939 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4940 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004941 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004942 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004943 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4944 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004945
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004946 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004947 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004948 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4949 AINPUT_SOURCE_MOUSE)
4950 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4951 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004952 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004953 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004954 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004955
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004956 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004957 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004958 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4959 AINPUT_SOURCE_MOUSE)
4960 .buttonState(0)
4961 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004962 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004963 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004964 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004965
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004966 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004967 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004968 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4969 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004970 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004971 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004972 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004973
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004974 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4975 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4976 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004977 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004978 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4979 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004980 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004981 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004982 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004983}
4984
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004985/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004986 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4987 * is generated.
4988 */
4989TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4990 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004991 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4992 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004993 window->setFrame(Rect(0, 0, 1200, 800));
4994
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004995 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004996
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004997 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004998
4999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005000 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005001 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
5002 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005003 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005004 .build()));
5005 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5006
5007 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005008 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005009 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
5010}
5011
5012/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07005013 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
5014 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00005015TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
5016 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
5017 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07005018 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005019 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5020 ui::LogicalDisplayId::DEFAULT);
Daniel Norman7487dfa2023-08-02 16:39:45 -07005021 window->setFrame(Rect(0, 0, 1200, 800));
5022
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005023 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Daniel Norman7487dfa2023-08-02 16:39:45 -07005024
5025 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5026
5027 MotionEventBuilder hoverEnterBuilder =
5028 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5029 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
5030 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
5031 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5032 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
5033 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5034 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
5035 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5036 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
5037}
5038
5039/**
Siarhei Vishniakou9d0d65e2024-08-02 12:10:05 -07005040 * Invalid events injected by input filter are rejected.
5041 */
5042TEST_F(InputDispatcherTest, InvalidA11yEventsGetRejected) {
5043 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5044 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5045 ui::LogicalDisplayId::DEFAULT);
5046
5047 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
5048
5049 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5050
5051 // a11y sets 'POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY' policy flag during injection, so define
5052 // a custom injection function here for convenience.
5053 auto injectFromAccessibility = [&](int32_t action, float x, float y) {
5054 MotionEvent event = MotionEventBuilder(action, AINPUT_SOURCE_TOUCHSCREEN)
5055 .pointer(PointerBuilder(0, ToolType::FINGER).x(x).y(y))
5056 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT)
5057 .build();
5058 return injectMotionEvent(*mDispatcher, event, 100ms,
5059 InputEventInjectionSync::WAIT_FOR_RESULT, /*targetUid=*/{},
5060 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_FILTERED |
5061 POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY);
5062 };
5063
5064 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5065 injectFromAccessibility(ACTION_DOWN, /*x=*/300, /*y=*/400));
5066 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5067 injectFromAccessibility(ACTION_MOVE, /*x=*/310, /*y=*/420));
5068 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5069 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5070 // finger is still down, so a new DOWN event should be rejected!
5071 ASSERT_EQ(InputEventInjectionResult::FAILED,
5072 injectFromAccessibility(ACTION_DOWN, /*x=*/340, /*y=*/410));
5073
5074 // if the gesture is correctly finished, new down event will succeed
5075 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5076 injectFromAccessibility(ACTION_MOVE, /*x=*/320, /*y=*/430));
5077 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5078 injectFromAccessibility(ACTION_UP, /*x=*/320, /*y=*/430));
5079 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5080 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
5081
5082 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
5083 injectFromAccessibility(ACTION_DOWN, /*x=*/350, /*y=*/460));
5084 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5085}
5086
5087/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005088 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
5089 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005090TEST_F(InputDispatcherTest, TouchDownAfterMouseHover_legacy) {
5091 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005092 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005093 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5094 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005095 window->setFrame(Rect(0, 0, 100, 100));
5096
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005097 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005098
5099 const int32_t mouseDeviceId = 7;
5100 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005101
5102 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00005103 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5104 .deviceId(mouseDeviceId)
5105 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
5106 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005107 window->consumeMotionEvent(
5108 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
5109
5110 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00005111 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5112 .deviceId(touchDeviceId)
5113 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5114 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08005115
5116 window->consumeMotionEvent(
5117 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
5118 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
5119}
5120
5121/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005122 * If mouse is hovering when the touch goes down, the hovering should not be stopped.
5123 */
5124TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
5125 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005127 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5128 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005129 window->setFrame(Rect(0, 0, 100, 100));
5130
5131 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5132
5133 const int32_t mouseDeviceId = 7;
5134 const int32_t touchDeviceId = 4;
5135
5136 // Start hovering with the mouse
5137 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
5138 .deviceId(mouseDeviceId)
5139 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
5140 .build());
5141 window->consumeMotionEvent(
5142 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
5143
5144 // Touch goes down
5145 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5146 .deviceId(touchDeviceId)
5147 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5148 .build());
5149 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
5150}
5151
5152/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005153 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005154 * The tap causes a HOVER_EXIT event to be generated because the current event
5155 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005156 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005157TEST_F(InputDispatcherTest, MouseHoverAndTouchTap_legacy) {
5158 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005159 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005160 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5161 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005162 window->setFrame(Rect(0, 0, 100, 100));
5163
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005164 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005165 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
5166 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
5167 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005168 ASSERT_NO_FATAL_FAILURE(
5169 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
5170 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005171
5172 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005173 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5174 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5175 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005176 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00005177 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
5178 WithSource(AINPUT_SOURCE_MOUSE))));
5179
5180 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005181 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
5182 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
5183
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005184 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5185 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5186 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08005187 ASSERT_NO_FATAL_FAILURE(
5188 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
5189 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
5190}
5191
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005192/**
5193 * Send a mouse hover event followed by a tap from touchscreen.
5194 * The tap causes a HOVER_EXIT event to be generated because the current event
5195 * stream's source has been switched.
5196 */
5197TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
5198 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5199 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005200 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5201 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07005202 window->setFrame(Rect(0, 0, 100, 100));
5203
5204 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
5205 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
5206 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
5207 .build());
5208
5209 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
5210 WithSource(AINPUT_SOURCE_MOUSE)));
5211
5212 // Tap on the window
5213 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5214 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5215 .build());
5216
5217 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
5218 WithSource(AINPUT_SOURCE_MOUSE)));
5219
5220 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
5221 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
5222
5223 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5224 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
5225 .build());
5226
5227 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
5228 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
5229}
5230
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005231TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
5232 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5233 sp<FakeWindowHandle> windowDefaultDisplay =
5234 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005235 ui::LogicalDisplayId::DEFAULT);
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005236 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
5237 sp<FakeWindowHandle> windowSecondDisplay =
5238 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
5239 SECOND_DISPLAY_ID);
5240 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
5241
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005242 mDispatcher->onWindowInfosChanged(
5243 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005244
5245 // Set cursor position in window in default display and check that hover enter and move
5246 // events are generated.
5247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005248 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005249 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5250 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005251 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005252 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005253 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005254 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005255
5256 // Remove all windows in secondary display and check that no event happens on window in
5257 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005258 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
5259
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005260 windowDefaultDisplay->assertNoEvents();
5261
5262 // Move cursor position in window in default display and check that only hover move
5263 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005264 mDispatcher->onWindowInfosChanged(
5265 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005266 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005267 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005268 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5269 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005270 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005271 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005272 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005273 windowDefaultDisplay->consumeMotionEvent(
5274 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
5275 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005276 windowDefaultDisplay->assertNoEvents();
5277}
5278
Garfield Tan00f511d2019-06-12 16:55:40 -07005279TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07005280 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07005281
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005282 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
5283 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005284 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005285 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
5286 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005287 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07005288
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005289 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tan00f511d2019-06-12 16:55:40 -07005290
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005291 mDispatcher->onWindowInfosChanged(
5292 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07005293
5294 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
5295 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005296 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005297 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005298 ui::LogicalDisplayId::DEFAULT, {610, 400}, {599, 400}));
5299 windowLeft->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005300 windowRight->assertNoEvents();
5301}
5302
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005303TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005304 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005305 sp<FakeWindowHandle> window =
5306 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5307 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07005308 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005309
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005310 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005311 setFocusedWindow(window);
5312
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005313 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005314
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005315 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005316
5317 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005318 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005319
5320 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
5321 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005322 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005323 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005324}
5325
5326TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005327 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005328 sp<FakeWindowHandle> window =
5329 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5330 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005331
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005332 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005333
Prabir Pradhan678438e2023-04-13 19:32:51 +00005334 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005335 AINPUT_SOURCE_TOUCHSCREEN,
5336 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005337
5338 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005339 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005340
5341 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
5342 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005343 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005344 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005345 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005346}
5347
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005348TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
5349 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005350 sp<FakeWindowHandle> window =
5351 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5352 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005353
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005354 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005355
5356 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5357 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
5358 .build());
5359
5360 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5361
5362 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
5363 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
5364 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5365
5366 // After the device has been reset, a new hovering stream can be sent to the window
5367 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5368 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
5369 .build());
5370 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5371}
5372
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005373TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
5374 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005375 sp<FakeWindowHandle> window =
5376 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5377 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005378 window->setFocusable(true);
5379
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005380 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005381 setFocusedWindow(window);
5382
5383 window->consumeFocusEvent(true);
5384
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005385 const NotifyKeyArgs keyArgs =
5386 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005387 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
5388 const nsecs_t injectTime = keyArgs.eventTime;
5389 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005390 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005391 // The dispatching time should be always greater than or equal to intercept key timeout.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005392 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005393 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
5394 std::chrono::nanoseconds(interceptKeyTimeout).count());
5395}
5396
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005397/**
5398 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
5399 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005400TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
5401 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005402 sp<FakeWindowHandle> window =
5403 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5404 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005405 window->setFocusable(true);
5406
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005407 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005408 setFocusedWindow(window);
5409
5410 window->consumeFocusEvent(true);
5411
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005412 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
5413 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005414
5415 // Set a value that's significantly larger than the default consumption timeout. If the
5416 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
5417 mFakePolicy->setInterceptKeyTimeout(600ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005418 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005419 // Window should receive key event immediately when same key up.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005420 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005421}
5422
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005423/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005424 * Two windows. First is a regular window. Second does not overlap with the first, and has
5425 * WATCH_OUTSIDE_TOUCH.
5426 * Both windows are owned by the same UID.
5427 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
5428 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
5429 */
5430TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
5431 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005432 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5433 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005434 window->setFrame(Rect{0, 0, 100, 100});
5435
5436 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005437 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005438 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005439 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5440 outsideWindow->setWatchOutsideTouch(true);
5441 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005442 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005443
5444 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005445 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005446 AINPUT_SOURCE_TOUCHSCREEN,
5447 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005448 window->consumeMotionDown();
5449 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
5450 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
5451 outsideWindow->consumeMotionEvent(
5452 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005453
5454 // Ensure outsideWindow doesn't get any more events for the gesture.
5455 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005456 ui::LogicalDisplayId::DEFAULT, {PointF{51, 51}}));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005457 window->consumeMotionMove();
5458 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005459}
5460
5461/**
Linnan Liccf6ce32024-04-11 20:32:13 +08005462 * Three windows:
5463 * - Left window
5464 * - Right window
5465 * - Outside window(watch for ACTION_OUTSIDE events)
5466 * The windows "left" and "outside" share the same owner, the window "right" has a different owner,
5467 * In order to allow the outside window can receive the ACTION_OUTSIDE events, the outside window is
5468 * positioned above the "left" and "right" windows, and it doesn't overlap with them.
5469 *
5470 * First, device A report a down event landed in the right window, the outside window can receive
5471 * an ACTION_OUTSIDE event that with zeroed coordinates, the device B report a down event landed
5472 * in the left window, the outside window can receive an ACTION_OUTSIDE event the with valid
5473 * coordinates, after these, device A and device B continue report MOVE event, the right and left
5474 * window can receive it, but outside window event can't receive it.
5475 */
5476TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinatesWhenMultiDevice) {
5477 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5478 sp<FakeWindowHandle> leftWindow =
5479 sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005480 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005481 leftWindow->setFrame(Rect{0, 0, 100, 100});
5482 leftWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5483
5484 sp<FakeWindowHandle> outsideWindow =
5485 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005486 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005487 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5488 outsideWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5489 outsideWindow->setWatchOutsideTouch(true);
5490
5491 std::shared_ptr<FakeApplicationHandle> anotherApplication =
5492 std::make_shared<FakeApplicationHandle>();
5493 sp<FakeWindowHandle> rightWindow =
5494 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Right Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005495 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005496 rightWindow->setFrame(Rect{100, 0, 200, 100});
5497 rightWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
5498
5499 // OutsideWindow must be above left window and right window to receive ACTION_OUTSIDE events
5500 // when left window or right window is tapped
5501 mDispatcher->onWindowInfosChanged(
5502 {{*outsideWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()},
5503 {},
5504 0,
5505 0});
5506
5507 const DeviceId deviceA = 9;
5508 const DeviceId deviceB = 3;
5509
5510 // Tap on right window use device A
5511 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5512 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5513 .deviceId(deviceA)
5514 .build());
5515 leftWindow->assertNoEvents();
5516 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5517 // Right window is belonged to another owner, so outsideWindow should receive ACTION_OUTSIDE
5518 // with zeroed coords.
5519 outsideWindow->consumeMotionEvent(
5520 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceA), WithCoords(0, 0)));
5521
5522 // Tap on left window use device B
5523 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5524 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5525 .deviceId(deviceB)
5526 .build());
5527 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5528 rightWindow->assertNoEvents();
5529 // Because new gesture down on the left window that has the same owner with outside Window, the
5530 // outside Window should receive the ACTION_OUTSIDE with coords.
5531 outsideWindow->consumeMotionEvent(
5532 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceB), WithCoords(-50, -50)));
5533
5534 // Ensure that windows that can only accept outside do not receive remaining gestures
5535 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5536 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
5537 .deviceId(deviceA)
5538 .build());
5539 leftWindow->assertNoEvents();
5540 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA)));
5541
5542 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5543 .pointer(PointerBuilder(0, ToolType::FINGER).x(51).y(51))
5544 .deviceId(deviceB)
5545 .build());
5546 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
5547 rightWindow->assertNoEvents();
5548 outsideWindow->assertNoEvents();
5549}
5550
5551/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005552 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
5553 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
5554 * ACTION_OUTSIDE event is sent per gesture.
5555 */
5556TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
5557 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
5558 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005559 sp<FakeWindowHandle> window =
5560 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5561 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005562 window->setWatchOutsideTouch(true);
5563 window->setFrame(Rect{0, 0, 100, 100});
5564 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005565 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005566 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005567 secondWindow->setFrame(Rect{100, 100, 200, 200});
5568 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005569 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005570 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005571 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005572 mDispatcher->onWindowInfosChanged(
5573 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005574
5575 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005576 mDispatcher->notifyMotion(
5577 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5578 ui::LogicalDisplayId::DEFAULT, {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005579 window->assertNoEvents();
5580 secondWindow->assertNoEvents();
5581
5582 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
5583 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005584 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005585 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005586 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005587 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
5588 window->consumeMotionEvent(
5589 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005590 secondWindow->consumeMotionDown();
5591 thirdWindow->assertNoEvents();
5592
5593 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
5594 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005595 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005596 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5597 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005598 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005599 window->assertNoEvents();
5600 secondWindow->consumeMotionMove();
5601 thirdWindow->consumeMotionDown();
5602}
5603
Prabir Pradhan814fe082022-07-22 20:22:18 +00005604TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
5605 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005606 sp<FakeWindowHandle> window =
5607 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5608 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005609 window->setFocusable(true);
5610
Patrick Williamsd828f302023-04-28 17:52:08 -05005611 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005612 setFocusedWindow(window);
5613
5614 window->consumeFocusEvent(true);
5615
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005616 const NotifyKeyArgs keyDown =
5617 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
5618 const NotifyKeyArgs keyUp =
5619 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005620 mDispatcher->notifyKey(keyDown);
5621 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005622
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005623 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5624 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005625
5626 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05005627 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005628
5629 window->consumeFocusEvent(false);
5630
Prabir Pradhan678438e2023-04-13 19:32:51 +00005631 mDispatcher->notifyKey(keyDown);
5632 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005633 window->assertNoEvents();
5634}
5635
Arthur Hung96483742022-11-15 03:30:48 +00005636TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07005637 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Arthur Hung96483742022-11-15 03:30:48 +00005638 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005639 sp<FakeWindowHandle> window =
5640 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5641 ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005642 // Ensure window is non-split and have some transform.
5643 window->setPreventSplitting(true);
5644 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05005645 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00005646
5647 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005648 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5649 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung96483742022-11-15 03:30:48 +00005650 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005651 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005652
5653 const MotionEvent secondFingerDownEvent =
5654 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005655 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung96483742022-11-15 03:30:48 +00005656 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005657 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5658 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00005659 .build();
5660 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005661 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00005662 InputEventInjectionSync::WAIT_FOR_RESULT))
5663 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5664
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005665 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
5666 ASSERT_NE(nullptr, event);
5667 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
5668 EXPECT_EQ(70, event->getX(0)); // 50 + 20
5669 EXPECT_EQ(90, event->getY(0)); // 50 + 40
5670 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
5671 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00005672}
5673
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005674/**
5675 * Two windows: a splittable and a non-splittable.
5676 * The non-splittable window shouldn't receive any "incomplete" gestures.
5677 * Send the first pointer to the splittable window, and then touch the non-splittable window.
5678 * The second pointer should be dropped because the initial window is splittable, so it won't get
5679 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
5680 * "incomplete" gestures.
5681 */
5682TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07005683 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005684 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5685 sp<FakeWindowHandle> leftWindow =
5686 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005687 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005688 leftWindow->setPreventSplitting(false);
5689 leftWindow->setFrame(Rect(0, 0, 100, 100));
5690 sp<FakeWindowHandle> rightWindow =
5691 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005692 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005693 rightWindow->setPreventSplitting(true);
5694 rightWindow->setFrame(Rect(100, 100, 200, 200));
5695 mDispatcher->onWindowInfosChanged(
5696 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5697
5698 // Touch down on left, splittable window
5699 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5700 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5701 .build());
5702 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5703
5704 mDispatcher->notifyMotion(
5705 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5706 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5707 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
5708 .build());
5709 leftWindow->assertNoEvents();
5710 rightWindow->assertNoEvents();
5711}
5712
Siarhei Vishniakou96204462024-07-13 23:59:47 -07005713/**
Siarhei Vishniakoufe346982024-08-07 00:17:19 +00005714 * Three windows:
5715 * 1) A window on the left, with flag dup_to_wallpaper
5716 * 2) A window on the right, with flag slippery
5717 * 3) A wallpaper window under the left window
5718 * When touch slips from right window to left, the wallpaper should receive a similar slippery
5719 * enter event. Later on, when another device becomes active, the wallpaper should receive
5720 * consistent streams from the new device, and also from the old device.
5721 * This test attempts to reproduce a crash in the dispatcher where the wallpaper target's downTime
5722 * was not getting set during slippery entrance.
5723 */
5724TEST_F(InputDispatcherTest, WallpaperWindowWhenSlipperyAndMultiWindowMultiTouch) {
5725 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
5726 std::shared_ptr<FakeApplicationHandle> application1 = std::make_shared<FakeApplicationHandle>();
5727 std::shared_ptr<FakeApplicationHandle> application2 = std::make_shared<FakeApplicationHandle>();
5728 std::shared_ptr<FakeApplicationHandle> application3 = std::make_shared<FakeApplicationHandle>();
5729 sp<FakeWindowHandle> wallpaper =
5730 sp<FakeWindowHandle>::make(application1, mDispatcher, "wallpaper",
5731 ui::LogicalDisplayId::DEFAULT);
5732 wallpaper->setIsWallpaper(true);
5733 wallpaper->setPreventSplitting(true);
5734 wallpaper->setTouchable(false);
5735
5736 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application2, mDispatcher, "Left",
5737 ui::LogicalDisplayId::DEFAULT);
5738 leftWindow->setTouchableRegion(Region{{0, 0, 100, 100}});
5739 leftWindow->setDupTouchToWallpaper(true);
5740
5741 sp<FakeWindowHandle> rightWindow =
5742 sp<FakeWindowHandle>::make(application3, mDispatcher, "Right",
5743 ui::LogicalDisplayId::DEFAULT);
5744 rightWindow->setTouchableRegion(Region{{100, 0, 200, 100}});
5745 rightWindow->setSlippery(true);
5746 rightWindow->setWatchOutsideTouch(true);
5747 rightWindow->setTrustedOverlay(true);
5748
5749 mDispatcher->onWindowInfosChanged(
5750 {{*rightWindow->getInfo(), *leftWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
5751
5752 const DeviceId deviceA = 3;
5753 const DeviceId deviceB = 9;
5754
5755 // First finger from device A into right window
5756 NotifyMotionArgs deviceADownArgs =
5757 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5758 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5759 .deviceId(deviceA)
5760 .build();
5761
5762 mDispatcher->notifyMotion(deviceADownArgs);
5763 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5764
5765 // Move the finger of device A from right window into left window. It should slip.
5766 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5767 .pointer(PointerBuilder(0, ToolType::FINGER).x(80).y(50))
5768 .deviceId(deviceA)
5769 .downTime(deviceADownArgs.downTime)
5770 .build());
5771
5772 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5773 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
5774 wallpaper->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5775
5776 // Finger from device B down into left window
5777 NotifyMotionArgs deviceBDownArgs =
5778 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5779 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
5780 .deviceId(deviceB)
5781 .build();
5782 mDispatcher->notifyMotion(deviceBDownArgs);
5783 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
5784 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
5785
5786 rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_OUTSIDE)));
5787
5788 // Move finger from device B, still keeping it in the left window
5789 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5790 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
5791 .deviceId(deviceB)
5792 .downTime(deviceBDownArgs.downTime)
5793 .build());
5794 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
5795 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
5796
5797 // Lift the finger from device B
5798 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5799 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
5800 .deviceId(deviceB)
5801 .downTime(deviceBDownArgs.downTime)
5802 .build());
5803 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
5804 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
5805
5806 // Move the finger of device A, keeping it in the left window
5807 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5808 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5809 .deviceId(deviceA)
5810 .downTime(deviceADownArgs.downTime)
5811 .build());
5812
5813 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE)));
5814 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE)));
5815
5816 // Second finger down from device A, into the right window. It should be split into:
5817 // MOVE for the left window (due to existing implementation) + a DOWN into the right window
5818 // Wallpaper will not receive this new pointer, and it will only get the MOVE event.
5819 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5820 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5821 .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
5822 .deviceId(deviceA)
5823 .downTime(deviceADownArgs.downTime)
5824 .build());
5825 auto firstFingerMoveFromDeviceA = AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_MOVE),
5826 WithPointerCount(1), WithPointerId(0, 0));
5827 leftWindow->consumeMotionEvent(firstFingerMoveFromDeviceA);
5828 wallpaper->consumeMotionEvent(firstFingerMoveFromDeviceA);
5829 rightWindow->consumeMotionEvent(
5830 AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_DOWN), WithPointerId(0, 1)));
5831
5832 // Lift up the second finger.
5833 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5834 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5835 .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
5836 .deviceId(deviceA)
5837 .downTime(deviceADownArgs.downTime)
5838 .build());
5839
5840 rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
5841 leftWindow->consumeMotionEvent(firstFingerMoveFromDeviceA);
5842 wallpaper->consumeMotionEvent(firstFingerMoveFromDeviceA);
5843
5844 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5845 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5846 .deviceId(deviceA)
5847 .downTime(deviceADownArgs.downTime)
5848 .build());
5849
5850 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
5851 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
5852 rightWindow->assertNoEvents();
5853}
5854
5855/**
5856 * Same test as above, but with enable_multi_device_same_window_stream flag set to false.
5857 */
5858TEST_F(InputDispatcherTest, WallpaperWindowWhenSlipperyAndMultiWindowMultiTouch_legacy) {
5859 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
5860 std::shared_ptr<FakeApplicationHandle> application1 = std::make_shared<FakeApplicationHandle>();
5861 std::shared_ptr<FakeApplicationHandle> application2 = std::make_shared<FakeApplicationHandle>();
5862 std::shared_ptr<FakeApplicationHandle> application3 = std::make_shared<FakeApplicationHandle>();
5863 sp<FakeWindowHandle> wallpaper =
5864 sp<FakeWindowHandle>::make(application1, mDispatcher, "wallpaper",
5865 ui::LogicalDisplayId::DEFAULT);
5866 wallpaper->setIsWallpaper(true);
5867 wallpaper->setPreventSplitting(true);
5868 wallpaper->setTouchable(false);
5869
5870 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application2, mDispatcher, "Left",
5871 ui::LogicalDisplayId::DEFAULT);
5872 leftWindow->setTouchableRegion(Region{{0, 0, 100, 100}});
5873 leftWindow->setDupTouchToWallpaper(true);
5874
5875 sp<FakeWindowHandle> rightWindow =
5876 sp<FakeWindowHandle>::make(application3, mDispatcher, "Right",
5877 ui::LogicalDisplayId::DEFAULT);
5878 rightWindow->setTouchableRegion(Region{{100, 0, 200, 100}});
5879 rightWindow->setSlippery(true);
5880 rightWindow->setWatchOutsideTouch(true);
5881 rightWindow->setTrustedOverlay(true);
5882
5883 mDispatcher->onWindowInfosChanged(
5884 {{*rightWindow->getInfo(), *leftWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
5885
5886 const DeviceId deviceA = 3;
5887 const DeviceId deviceB = 9;
5888
5889 // First finger from device A into right window
5890 NotifyMotionArgs deviceADownArgs =
5891 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5892 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5893 .deviceId(deviceA)
5894 .build();
5895
5896 mDispatcher->notifyMotion(deviceADownArgs);
5897 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5898
5899 // Move the finger of device A from right window into left window. It should slip.
5900 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5901 .pointer(PointerBuilder(0, ToolType::FINGER).x(80).y(50))
5902 .deviceId(deviceA)
5903 .downTime(deviceADownArgs.downTime)
5904 .build());
5905
5906 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5907 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
5908 wallpaper->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5909
5910 // Finger from device B down into left window
5911 NotifyMotionArgs deviceBDownArgs =
5912 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5913 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
5914 .deviceId(deviceB)
5915 .build();
5916 mDispatcher->notifyMotion(deviceBDownArgs);
5917 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_CANCEL)));
5918 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
5919 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_CANCEL)));
5920 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_DOWN)));
5921
5922 rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_OUTSIDE)));
5923
5924 // Move finger from device B, still keeping it in the left window
5925 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5926 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
5927 .deviceId(deviceB)
5928 .downTime(deviceBDownArgs.downTime)
5929 .build());
5930 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
5931 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_MOVE)));
5932
5933 // Lift the finger from device B
5934 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5935 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(50))
5936 .deviceId(deviceB)
5937 .downTime(deviceBDownArgs.downTime)
5938 .build());
5939 leftWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
5940 wallpaper->consumeMotionEvent(AllOf(WithDeviceId(deviceB), WithMotionAction(ACTION_UP)));
5941
5942 // Move the finger of device A, keeping it in the left window
5943 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5944 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5945 .deviceId(deviceA)
5946 .downTime(deviceADownArgs.downTime)
5947 .build());
5948 // This device was already canceled, so MOVE events will not be arriving to the windows from it.
5949
5950 // Second finger down from device A, into the right window. It should be split into:
5951 // MOVE for the left window (due to existing implementation) + a DOWN into the right window
5952 // Wallpaper will not receive this new pointer, and it will only get the MOVE event.
5953 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5954 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5955 .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
5956 .deviceId(deviceA)
5957 .downTime(deviceADownArgs.downTime)
5958 .build());
5959 rightWindow->consumeMotionEvent(
5960 AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_DOWN), WithPointerId(0, 1)));
5961
5962 // Lift up the second finger.
5963 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5964 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5965 .pointer(PointerBuilder(1, ToolType::FINGER).x(140).y(50))
5966 .deviceId(deviceA)
5967 .downTime(deviceADownArgs.downTime)
5968 .build());
5969
5970 rightWindow->consumeMotionEvent(AllOf(WithDeviceId(deviceA), WithMotionAction(ACTION_UP)));
5971
5972 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5973 .pointer(PointerBuilder(0, ToolType::FINGER).x(70).y(50))
5974 .deviceId(deviceA)
5975 .downTime(deviceADownArgs.downTime)
5976 .build());
5977 rightWindow->assertNoEvents();
5978}
5979
5980/**
Siarhei Vishniakou96204462024-07-13 23:59:47 -07005981 * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a
5982 * down event to the right window. Device B sends a down event to the left window, and then a
5983 * POINTER_DOWN event to the right window. However, since the left window prevents splitting, the
5984 * POINTER_DOWN event should only go to the left window, and not to the right window.
5985 * This test attempts to reproduce a crash.
5986 */
5987TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07005988 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Siarhei Vishniakou96204462024-07-13 23:59:47 -07005989 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5990 sp<FakeWindowHandle> leftWindow =
5991 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)",
5992 ui::LogicalDisplayId::DEFAULT);
5993 leftWindow->setFrame(Rect(0, 0, 100, 100));
5994 leftWindow->setPreventSplitting(true);
5995
5996 sp<FakeWindowHandle> rightWindow =
5997 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
5998 ui::LogicalDisplayId::DEFAULT);
5999 rightWindow->setFrame(Rect(100, 0, 200, 100));
6000
6001 mDispatcher->onWindowInfosChanged(
6002 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
6003
6004 const DeviceId deviceA = 9;
6005 const DeviceId deviceB = 3;
6006 // Touch the right window with device A
6007 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6008 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6009 .deviceId(deviceA)
6010 .build());
6011 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
6012 // Touch the left window with device B
6013 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6014 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6015 .deviceId(deviceB)
6016 .build());
6017 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
6018 // Send a second pointer from device B to the right window. It shouldn't go to the right window
6019 // because the left window prevents splitting.
6020 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6021 .deviceId(deviceB)
6022 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6023 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6024 .build());
6025 leftWindow->consumeMotionPointerDown(1, WithDeviceId(deviceB));
6026
6027 // Finish the gesture for both devices
6028 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6029 .deviceId(deviceB)
6030 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6031 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
6032 .build());
6033 leftWindow->consumeMotionPointerUp(1, WithDeviceId(deviceB));
6034 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6035 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
6036 .deviceId(deviceB)
6037 .build());
6038 leftWindow->consumeMotionEvent(
6039 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithPointerId(0, 0)));
6040 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6041 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
6042 .deviceId(deviceA)
6043 .build());
6044 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA)));
6045}
6046
Harry Cuttsb166c002023-05-09 13:06:05 +00006047TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
6048 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006049 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6050 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00006051 window->setFrame(Rect(0, 0, 400, 400));
6052 sp<FakeWindowHandle> trustedOverlay =
6053 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006054 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00006055 trustedOverlay->setSpy(true);
6056 trustedOverlay->setTrustedOverlay(true);
6057
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006058 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00006059
6060 // Start a three-finger touchpad swipe
6061 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6062 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6063 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6064 .build());
6065 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
6066 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6067 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6068 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6069 .build());
6070 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
6071 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6072 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6073 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
6074 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6075 .build());
6076
6077 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6078 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
6079 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
6080
6081 // Move the swipe a bit
6082 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
6083 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6084 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6085 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6086 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6087 .build());
6088
6089 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
6090
6091 // End the swipe
6092 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
6093 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6094 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6095 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6096 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6097 .build());
6098 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
6099 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6100 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6101 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6102 .build());
6103 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
6104 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6105 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6106 .build());
6107
6108 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
6109 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
6110 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
6111
6112 window->assertNoEvents();
6113}
6114
6115TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
6116 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006117 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6118 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00006119 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006120 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00006121
6122 // Start a three-finger touchpad swipe
6123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
6124 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6125 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6126 .build());
6127 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
6128 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6129 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6130 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6131 .build());
6132 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
6133 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
6134 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
6135 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
6136 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6137 .build());
6138
6139 // Move the swipe a bit
6140 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
6141 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6142 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6143 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6144 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6145 .build());
6146
6147 // End the swipe
6148 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
6149 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6150 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6151 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
6152 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6153 .build());
6154 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
6155 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6156 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
6157 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6158 .build());
6159 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
6160 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
6161 .classification(MotionClassification::MULTI_FINGER_SWIPE)
6162 .build());
6163
6164 window->assertNoEvents();
6165}
6166
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00006167/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006168 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
6169 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00006170 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006171 */
6172TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
6173 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006174 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6175 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006176 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07006177 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006178
6179 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
6180 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6181 .downTime(baseTime + 10)
6182 .eventTime(baseTime + 10)
6183 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6184 .build());
6185
6186 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
6187
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006188 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07006189 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006190
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07006191 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006192
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006193 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6194 .downTime(baseTime + 10)
6195 .eventTime(baseTime + 30)
6196 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6197 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
6198 .build());
6199
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00006200 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
6201
6202 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006203 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
6204 .downTime(baseTime + 10)
6205 .eventTime(baseTime + 40)
6206 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6207 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
6208 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00006209
6210 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
6211
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006212 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
6213 .downTime(baseTime + 10)
6214 .eventTime(baseTime + 50)
6215 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
6216 .build());
6217
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00006218 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
6219
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006220 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
6221 .downTime(baseTime + 60)
6222 .eventTime(baseTime + 60)
6223 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
6224 .build());
6225
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07006226 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006227}
6228
6229/**
Hu Guo771a7692023-09-17 20:51:08 +08006230 * When there are multiple screens, such as screen projection to TV or screen recording, if the
6231 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
6232 * its coordinates should be converted by the transform of the windows of target screen.
6233 */
6234TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
6235 // This case will create a window and a spy window on the default display and mirror
6236 // window on the second display. cancel event is sent through spy window pilferPointers
6237 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6238
6239 sp<FakeWindowHandle> spyWindowDefaultDisplay =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006240 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6241 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08006242 spyWindowDefaultDisplay->setTrustedOverlay(true);
6243 spyWindowDefaultDisplay->setSpy(true);
6244
6245 sp<FakeWindowHandle> windowDefaultDisplay =
6246 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006247 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08006248 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
6249
6250 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
6251 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
6252
6253 // Add the windows to the dispatcher
6254 mDispatcher->onWindowInfosChanged(
6255 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
6256 *windowSecondDisplay->getInfo()},
6257 {},
6258 0,
6259 0});
6260
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006261 // Send down to ui::LogicalDisplayId::DEFAULT
Hu Guo771a7692023-09-17 20:51:08 +08006262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006263 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6264 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Hu Guo771a7692023-09-17 20:51:08 +08006265 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6266
6267 spyWindowDefaultDisplay->consumeMotionDown();
6268 windowDefaultDisplay->consumeMotionDown();
6269
6270 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
6271
6272 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006273 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
6274 ASSERT_NE(nullptr, event);
6275 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08006276
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006277 // The cancel event is sent to windowDefaultDisplay of the ui::LogicalDisplayId::DEFAULT
6278 // display, so the coordinates of the cancel are converted by windowDefaultDisplay's transform,
6279 // the x and y coordinates are both 100, otherwise if the cancel event is sent to
6280 // windowSecondDisplay of SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006281 EXPECT_EQ(100, event->getX(0));
6282 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08006283}
6284
6285/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006286 * Ensure the correct coordinate spaces are used by InputDispatcher.
6287 *
6288 * InputDispatcher works in the display space, so its coordinate system is relative to the display
6289 * panel. Windows get events in the window space, and get raw coordinates in the logical display
6290 * space.
6291 */
6292class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
6293public:
6294 void SetUp() override {
6295 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006296 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006297 }
6298
Linnan Li13bf76a2024-05-05 19:18:02 +08006299 void addDisplayInfo(ui::LogicalDisplayId displayId, const ui::Transform& transform) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006300 gui::DisplayInfo info;
6301 info.displayId = displayId;
6302 info.transform = transform;
6303 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05006304 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006305 }
6306
6307 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
6308 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05006309 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006310 }
6311
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006312 void removeAllWindowsAndDisplays() {
6313 mDisplayInfos.clear();
6314 mWindowInfos.clear();
6315 }
6316
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006317 // Set up a test scenario where the display has a scaled projection and there are two windows
6318 // on the display.
6319 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
6320 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
6321 // respectively.
6322 ui::Transform displayTransform;
6323 displayTransform.set(2, 0, 0, 4);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006324 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006325
6326 std::shared_ptr<FakeApplicationHandle> application =
6327 std::make_shared<FakeApplicationHandle>();
6328
6329 // Add two windows to the display. Their frames are represented in the display space.
6330 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006331 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006332 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006333 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
6334 addWindow(firstWindow);
6335
6336 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006337 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006338 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006339 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
6340 addWindow(secondWindow);
6341 return {std::move(firstWindow), std::move(secondWindow)};
6342 }
6343
6344private:
6345 std::vector<gui::DisplayInfo> mDisplayInfos;
6346 std::vector<gui::WindowInfo> mWindowInfos;
6347};
6348
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006349TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006350 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6351 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006352 // selected so that if the hit test was performed with the point and the bounds being in
6353 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006354 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006355 AINPUT_SOURCE_TOUCHSCREEN,
6356 ui::LogicalDisplayId::DEFAULT, {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006357
6358 firstWindow->consumeMotionDown();
6359 secondWindow->assertNoEvents();
6360}
6361
6362// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
6363// the event should be treated as being in the logical display space.
6364TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
6365 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6366 // Send down to the first window. The point is represented in the logical display space. The
6367 // point is selected so that if the hit test was done in logical display space, then it would
6368 // end up in the incorrect window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006369 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006370 PointF{75 * 2, 55 * 4});
6371
6372 firstWindow->consumeMotionDown();
6373 secondWindow->assertNoEvents();
6374}
6375
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006376// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
6377// event should be treated as being in the logical display space.
6378TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
6379 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6380
6381 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6382 ui::Transform injectedEventTransform;
6383 injectedEventTransform.set(matrix);
6384 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
6385 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
6386
6387 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006388 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006389 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07006390 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006391 .x(untransformedPoint.x)
6392 .y(untransformedPoint.y))
6393 .build();
6394 event.transform(matrix);
6395
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006396 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00006397 InputEventInjectionSync::WAIT_FOR_RESULT);
6398
6399 firstWindow->consumeMotionDown();
6400 secondWindow->assertNoEvents();
6401}
6402
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006403TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
6404 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6405
6406 // Send down to the second window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006407 mDispatcher->notifyMotion(
6408 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6409 ui::LogicalDisplayId::DEFAULT, {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006410
6411 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006412 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
6413 ASSERT_NE(nullptr, event);
6414 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006415
6416 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006417 EXPECT_EQ(300, event->getRawX(0));
6418 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006419
6420 // Ensure that the x and y values are in the window's coordinate space.
6421 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
6422 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006423 EXPECT_EQ(100, event->getX(0));
6424 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07006425}
6426
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006427TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
6428 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6429 // The monitor will always receive events in the logical display's coordinate space, because
6430 // it does not have a window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006431 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ui::LogicalDisplayId::DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006432
6433 // Send down to the first window.
6434 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006435 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006436 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6437 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6438
6439 // Second pointer goes down on second window.
6440 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006441 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00006442 {PointF{50, 100}, PointF{150, 220}}));
6443 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
6444 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
6445 {1, PointF{300, 880}}};
6446 monitor.consumeMotionEvent(
6447 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
6448
6449 mDispatcher->cancelCurrentTouch();
6450
6451 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
6452 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
6453 monitor.consumeMotionEvent(
6454 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
6455}
6456
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006457TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
6458 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6459
6460 // Send down to the first window.
6461 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006462 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006463 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
6464
6465 // The pointer is transferred to the second window, and the second window receives it in the
6466 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006467 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00006468 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
6469 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
6470}
6471
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006472TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
6473 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6474
6475 // Send hover move to the second window, and ensure it shows up as hover enter.
6476 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006477 ui::LogicalDisplayId::DEFAULT,
6478 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006479 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6480 WithCoords(100, 80), WithRawCoords(300, 880)));
6481
6482 // Touch down at the same location and ensure a hover exit is synthesized.
6483 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006484 ui::LogicalDisplayId::DEFAULT,
6485 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006486 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6487 WithRawCoords(300, 880)));
6488 secondWindow->consumeMotionEvent(
6489 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
6490 secondWindow->assertNoEvents();
6491 firstWindow->assertNoEvents();
6492}
6493
Prabir Pradhan453ae732023-10-13 14:30:14 +00006494// Same as above, but while the window is being mirrored.
6495TEST_F(InputDispatcherDisplayProjectionTest,
6496 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
6497 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6498
6499 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6500 ui::Transform secondDisplayTransform;
6501 secondDisplayTransform.set(matrix);
6502 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
6503
6504 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
6505 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
6506 addWindow(secondWindowClone);
6507
6508 // Send hover move to the second window, and ensure it shows up as hover enter.
6509 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006510 ui::LogicalDisplayId::DEFAULT,
6511 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00006512 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6513 WithCoords(100, 80), WithRawCoords(300, 880)));
6514
6515 // Touch down at the same location and ensure a hover exit is synthesized for the correct
6516 // display.
6517 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006518 ui::LogicalDisplayId::DEFAULT,
6519 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00006520 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6521 WithRawCoords(300, 880)));
6522 secondWindow->consumeMotionEvent(
6523 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
6524 secondWindow->assertNoEvents();
6525 firstWindow->assertNoEvents();
6526}
6527
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006528TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
6529 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6530
6531 // Send hover enter to second window
6532 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006533 ui::LogicalDisplayId::DEFAULT,
6534 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006535 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6536 WithCoords(100, 80), WithRawCoords(300, 880)));
6537
6538 mDispatcher->cancelCurrentTouch();
6539
6540 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6541 WithRawCoords(300, 880)));
6542 secondWindow->assertNoEvents();
6543 firstWindow->assertNoEvents();
6544}
6545
Prabir Pradhan453ae732023-10-13 14:30:14 +00006546// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00006547TEST_F(InputDispatcherDisplayProjectionTest,
6548 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
6549 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6550
6551 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6552 ui::Transform secondDisplayTransform;
6553 secondDisplayTransform.set(matrix);
6554 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
6555
6556 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
6557 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
6558 addWindow(secondWindowClone);
6559
6560 // Send hover enter to second window
6561 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006562 ui::LogicalDisplayId::DEFAULT,
6563 {PointF{150, 220}}));
Prabir Pradhan16463382023-10-12 23:03:19 +00006564 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6565 WithCoords(100, 80), WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006566 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00006567
6568 mDispatcher->cancelCurrentTouch();
6569
6570 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
6571 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6572 WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006573 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00006574 secondWindow->assertNoEvents();
6575 firstWindow->assertNoEvents();
6576}
6577
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006578/** Ensure consistent behavior of InputDispatcher in all orientations. */
6579class InputDispatcherDisplayOrientationFixture
6580 : public InputDispatcherDisplayProjectionTest,
6581 public ::testing::WithParamInterface<ui::Rotation> {};
6582
6583// This test verifies the touchable region of a window for all rotations of the display by tapping
6584// in different locations on the display, specifically points close to the four corners of a
6585// window.
6586TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
6587 constexpr static int32_t displayWidth = 400;
6588 constexpr static int32_t displayHeight = 800;
6589
6590 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6591
6592 const auto rotation = GetParam();
6593
6594 // Set up the display with the specified rotation.
6595 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6596 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6597 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6598 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6599 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006600 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006601
6602 // Create a window with its bounds determined in the logical display.
6603 const Rect frameInLogicalDisplay(100, 100, 200, 300);
6604 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006605 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6606 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006607 window->setFrame(frameInDisplay, displayTransform);
6608 addWindow(window);
6609
6610 // The following points in logical display space should be inside the window.
6611 static const std::array<vec2, 4> insidePoints{
6612 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6613 for (const auto pointInsideWindow : insidePoints) {
6614 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
6615 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006616 mDispatcher->notifyMotion(
6617 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6618 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006619 window->consumeMotionDown();
6620
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006621 mDispatcher->notifyMotion(
6622 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6623 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006624 window->consumeMotionUp();
6625 }
6626
6627 // The following points in logical display space should be outside the window.
6628 static const std::array<vec2, 5> outsidePoints{
6629 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6630 for (const auto pointOutsideWindow : outsidePoints) {
6631 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
6632 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006633 mDispatcher->notifyMotion(
6634 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6635 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006636
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006637 mDispatcher->notifyMotion(
6638 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6639 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006640 }
6641 window->assertNoEvents();
6642}
6643
Linnan Li5e5645e2024-03-05 14:43:05 +00006644// This test verifies the occlusion detection for all rotations of the display by tapping
6645// in different locations on the display, specifically points close to the four corners of a
6646// window.
6647TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) {
6648 constexpr static int32_t displayWidth = 400;
6649 constexpr static int32_t displayHeight = 800;
6650
6651 std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication =
6652 std::make_shared<FakeApplicationHandle>();
6653 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6654
6655 const auto rotation = GetParam();
6656
6657 // Set up the display with the specified rotation.
6658 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6659 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6660 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6661 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6662 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006663 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Linnan Li5e5645e2024-03-05 14:43:05 +00006664
6665 // Create a window that not trusted.
6666 const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
6667
6668 const Rect untrustedWindowFrameInDisplay =
6669 displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay);
6670
6671 sp<FakeWindowHandle> untrustedWindow =
6672 sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006673 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006674 untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
6675 untrustedWindow->setTrustedOverlay(false);
6676 untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
6677 untrustedWindow->setTouchable(false);
6678 untrustedWindow->setAlpha(1.0f);
6679 untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
6680 addWindow(untrustedWindow);
6681
6682 // Create a simple app window below the untrusted window.
6683 const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600);
6684 const Rect simpleAppWindowFrameInDisplay =
6685 displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay);
6686
6687 sp<FakeWindowHandle> simpleAppWindow =
6688 sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006689 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006690 simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
6691 simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
6692 addWindow(simpleAppWindow);
6693
6694 // The following points in logical display space should be inside the untrusted window, so
6695 // the simple window could not receive events that coordinate is these point.
6696 static const std::array<vec2, 4> untrustedPoints{
6697 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6698
6699 for (const auto untrustedPoint : untrustedPoints) {
6700 const vec2 p = displayTransform.inverse().transform(untrustedPoint);
6701 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006702 mDispatcher->notifyMotion(
6703 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6704 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6705 mDispatcher->notifyMotion(
6706 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6707 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Linnan Li5e5645e2024-03-05 14:43:05 +00006708 }
6709 untrustedWindow->assertNoEvents();
6710 simpleAppWindow->assertNoEvents();
6711 // The following points in logical display space should be outside the untrusted window, so
6712 // the simple window should receive events that coordinate is these point.
6713 static const std::array<vec2, 5> trustedPoints{
6714 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6715 for (const auto trustedPoint : trustedPoints) {
6716 const vec2 p = displayTransform.inverse().transform(trustedPoint);
6717 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006718 mDispatcher->notifyMotion(
6719 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6720 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6721 simpleAppWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006722 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006723 mDispatcher->notifyMotion(
6724 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6725 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6726 simpleAppWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006727 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6728 }
6729 untrustedWindow->assertNoEvents();
6730}
6731
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006732// Run the precision tests for all rotations.
6733INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
6734 InputDispatcherDisplayOrientationFixture,
6735 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6736 ui::ROTATION_270),
6737 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6738 return ftl::enum_string(testParamInfo.param);
6739 });
6740
Siarhei Vishniakou18050092021-09-01 13:32:49 -07006741using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
6742 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006743
6744class TransferTouchFixture : public InputDispatcherTest,
6745 public ::testing::WithParamInterface<TransferFunction> {};
6746
6747TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07006748 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006749
6750 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006751 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006752 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006753 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006754 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006755 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006756 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006757 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006758 sp<FakeWindowHandle> wallpaper =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006759 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
6760 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006761 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006762 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006763 mDispatcher->onWindowInfosChanged(
6764 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00006765 setFocusedWindow(firstWindow);
6766 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006767
6768 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006769 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006770 AINPUT_SOURCE_TOUCHSCREEN,
6771 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006772
Svet Ganov5d3bc372020-01-26 23:11:07 -08006773 // Only the first window should get the down event
6774 firstWindow->consumeMotionDown();
6775 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006776 wallpaper->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006777 // Dispatcher reports pointer down outside focus for the wallpaper
6778 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006779
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006780 // Transfer touch to the second window
6781 TransferFunction f = GetParam();
6782 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6783 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006784 // The first window gets cancel and the second gets down
6785 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006786 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6787 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6788 wallpaper->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006789 // There should not be any changes to the focused window when transferring touch
6790 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006791
6792 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006793 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006794 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00006795 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08006796 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006797 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6798 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006799 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006800}
6801
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006802/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00006803 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
6804 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
6805 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006806 * natural to the user.
6807 * In this test, we are sending a pointer to both spy window and first window. We then try to
6808 * transfer touch to the second window. The dispatcher should identify the first window as the
6809 * one that should lose the gesture, and therefore the action should be to move the gesture from
6810 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006811 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
6812 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006813 */
6814TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
6815 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6816
6817 // Create a couple of windows + a spy window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006818 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6819 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006820 spyWindow->setTrustedOverlay(true);
6821 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006822 sp<FakeWindowHandle> firstWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "First",
6823 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006824 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006825 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
6826 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006827
6828 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006829 mDispatcher->onWindowInfosChanged(
6830 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006831
6832 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006833 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006834 AINPUT_SOURCE_TOUCHSCREEN,
6835 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006836 // Only the first window and spy should get the down event
6837 spyWindow->consumeMotionDown();
6838 firstWindow->consumeMotionDown();
6839
6840 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00006841 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006842 TransferFunction f = GetParam();
6843 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6844 ASSERT_TRUE(success);
6845 // The first window gets cancel and the second gets down
6846 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006847 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6848 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006849
6850 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006851 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006852 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006853 // The first window gets no events and the second+spy get up
6854 firstWindow->assertNoEvents();
6855 spyWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006856 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6857 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006858}
6859
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006860TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006861 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006862
6863 PointF touchPoint = {10, 10};
6864
6865 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006866 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006867 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006868 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006869 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006870 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006871 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006872 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006873 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006874
6875 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006876 mDispatcher->onWindowInfosChanged(
6877 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006878
6879 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006880 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006881 AINPUT_SOURCE_TOUCHSCREEN,
6882 ui::LogicalDisplayId::DEFAULT, {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006883 // Only the first window should get the down event
6884 firstWindow->consumeMotionDown();
6885 secondWindow->assertNoEvents();
6886
6887 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006888 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006889 ui::LogicalDisplayId::DEFAULT,
6890 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006891 // Only the first window should get the pointer down event
6892 firstWindow->consumeMotionPointerDown(1);
6893 secondWindow->assertNoEvents();
6894
6895 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006896 TransferFunction f = GetParam();
6897 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6898 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006899 // The first window gets cancel and the second gets down and pointer down
6900 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006901 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6902 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6903 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006904 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006905
6906 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006907 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006908 ui::LogicalDisplayId::DEFAULT,
6909 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006910 // The first window gets nothing and the second gets pointer up
6911 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00006912 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
6913 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
6914 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
6915 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006916
6917 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006918 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006919 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006920 // The first window gets nothing and the second gets up
6921 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006922 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6923 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006924}
6925
Arthur Hungc539dbb2022-12-08 07:45:36 +00006926TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
6927 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6928
6929 // Create a couple of windows
6930 sp<FakeWindowHandle> firstWindow =
6931 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006932 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006933 firstWindow->setDupTouchToWallpaper(true);
6934 sp<FakeWindowHandle> secondWindow =
6935 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006936 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006937 secondWindow->setDupTouchToWallpaper(true);
6938
6939 sp<FakeWindowHandle> wallpaper1 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006940 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1",
6941 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006942 wallpaper1->setIsWallpaper(true);
6943
6944 sp<FakeWindowHandle> wallpaper2 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006945 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2",
6946 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006947 wallpaper2->setIsWallpaper(true);
6948 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006949 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
6950 *secondWindow->getInfo(), *wallpaper2->getInfo()},
6951 {},
6952 0,
6953 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00006954
6955 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006956 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006957 AINPUT_SOURCE_TOUCHSCREEN,
6958 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006959
6960 // Only the first window should get the down event
6961 firstWindow->consumeMotionDown();
6962 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006963 wallpaper1->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006964 wallpaper2->assertNoEvents();
6965
6966 // Transfer touch focus to the second window
6967 TransferFunction f = GetParam();
6968 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6969 ASSERT_TRUE(success);
6970
6971 // The first window gets cancel and the second gets down
6972 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006973 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6974 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6975 wallpaper1->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
6976 wallpaper2->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006977 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006978
6979 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006980 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006981 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006982 // The first window gets no events and the second gets up
6983 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006984 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6985 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006986 wallpaper1->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006987 wallpaper2->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006988 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006989}
6990
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006991// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00006992// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006993// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006994INSTANTIATE_TEST_SUITE_P(
6995 InputDispatcherTransferFunctionTests, TransferTouchFixture,
6996 ::testing::Values(
6997 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
6998 sp<IBinder> destChannelToken) {
6999 return dispatcher->transferTouchOnDisplay(destChannelToken,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007000 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00007001 },
7002 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
7003 sp<IBinder> to) {
7004 return dispatcher->transferTouchGesture(from, to,
7005 /*isDragAndDrop=*/false);
7006 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007007
Prabir Pradhan367f3432024-02-13 23:05:58 +00007008TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07007009 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08007010
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007011 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007012 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007013 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007014 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007015
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007016 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007017 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007018 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007019 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007020
7021 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007022 mDispatcher->onWindowInfosChanged(
7023 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08007024
7025 PointF pointInFirst = {300, 200};
7026 PointF pointInSecond = {300, 600};
7027
7028 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007029 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007030 AINPUT_SOURCE_TOUCHSCREEN,
7031 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007032 // Only the first window should get the down event
7033 firstWindow->consumeMotionDown();
7034 secondWindow->assertNoEvents();
7035
7036 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007037 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007038 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007039 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007040 // The first window gets a move and the second a down
7041 firstWindow->consumeMotionMove();
7042 secondWindow->consumeMotionDown();
7043
Prabir Pradhan367f3432024-02-13 23:05:58 +00007044 // Transfer touch to the second window
7045 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08007046 // The first window gets cancel and the new gets pointer down (it already saw down)
7047 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007048 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00007049 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007050
7051 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007052 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007053 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007054 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007055 // The first window gets nothing and the second gets pointer up
7056 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00007057 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
7058 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
7059 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
7060 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007061
7062 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007063 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007064 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08007065 // The first window gets nothing and the second gets up
7066 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007067 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7068 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08007069}
7070
Prabir Pradhan367f3432024-02-13 23:05:58 +00007071// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
7072// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
7073// receiving touch is not supported, so the touch should continue on those windows and the
7074// transferred-to window should get nothing.
7075TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007076 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7077
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007078 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007079 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007080 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007081 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007082
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007083 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007084 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007085 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007086 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007087
7088 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007089 mDispatcher->onWindowInfosChanged(
7090 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007091
7092 PointF pointInFirst = {300, 200};
7093 PointF pointInSecond = {300, 600};
7094
7095 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007096 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007097 AINPUT_SOURCE_TOUCHSCREEN,
7098 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007099 // Only the first window should get the down event
7100 firstWindow->consumeMotionDown();
7101 secondWindow->assertNoEvents();
7102
7103 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007104 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007105 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007106 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007107 // The first window gets a move and the second a down
7108 firstWindow->consumeMotionMove();
7109 secondWindow->consumeMotionDown();
7110
7111 // Transfer touch focus to the second window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007112 const bool transferred = mDispatcher->transferTouchOnDisplay(secondWindow->getToken(),
7113 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00007114 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007115 ASSERT_FALSE(transferred);
7116 firstWindow->assertNoEvents();
7117 secondWindow->assertNoEvents();
7118
7119 // The rest of the dispatch should proceed as normal
7120 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007121 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007122 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007123 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007124 // The first window gets MOVE and the second gets pointer up
7125 firstWindow->consumeMotionMove();
7126 secondWindow->consumeMotionUp();
7127
7128 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007129 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007130 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00007131 // The first window gets nothing and the second gets up
7132 firstWindow->consumeMotionUp();
7133 secondWindow->assertNoEvents();
7134}
7135
Arthur Hungabbb9d82021-09-01 14:52:30 +00007136// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00007137// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00007138// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00007139TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00007140 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7141 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007142 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
7143 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007144 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007145 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007146 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
7147 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007148 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007149
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007150 sp<FakeWindowHandle> mirrorWindowInPrimary =
7151 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007152 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007153
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007154 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007155 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007156
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007157 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007158 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007159
7160 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007161 mDispatcher->onWindowInfosChanged(
7162 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
7163 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
7164 *secondWindowInPrimary->getInfo()},
7165 {},
7166 0,
7167 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00007168
7169 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007170 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7171 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00007172 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7173
7174 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007175 firstWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007176
Prabir Pradhan367f3432024-02-13 23:05:58 +00007177 // Transfer touch
7178 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
7179 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007180 // The first window gets cancel.
7181 firstWindowInPrimary->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007182 secondWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00007183 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007184
7185 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007186 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007187 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00007188 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7189 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007190 secondWindowInPrimary->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00007191 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007192
7193 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007194 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00007195 {150, 50}))
7196 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7197 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007198 secondWindowInPrimary->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
7199 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007200}
7201
Prabir Pradhan367f3432024-02-13 23:05:58 +00007202// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
7203// 'transferTouchOnDisplay' api.
7204TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00007205 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7206 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007207 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
7208 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007209 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007210 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007211 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
7212 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007213 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007214
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007215 sp<FakeWindowHandle> mirrorWindowInPrimary =
7216 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007217 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007218
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007219 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007220 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007221
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07007222 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007223 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007224
7225 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007226 mDispatcher->onWindowInfosChanged(
7227 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
7228 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
7229 *secondWindowInPrimary->getInfo()},
7230 {},
7231 0,
7232 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00007233
7234 // Touch on second display.
7235 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007236 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7237 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00007238 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7239
7240 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007241 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007242
7243 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00007244 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
7245 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00007246
7247 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007248 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00007249 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
7250 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007251
7252 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007253 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00007254 SECOND_DISPLAY_ID, {150, 50}))
7255 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007256 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00007257 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
7258 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007259
7260 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007261 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00007262 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00007263 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00007264 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00007265}
7266
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007267TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007268 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007269 sp<FakeWindowHandle> window =
7270 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7271 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007272
Vishnu Nair47074b82020-08-14 11:54:47 -07007273 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007274 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007275 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007276
7277 window->consumeFocusEvent(true);
7278
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007279 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007280
7281 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007282 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007283
7284 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00007285 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00007286 mFakePolicy->assertUserActivityPoked();
7287}
7288
7289TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
7290 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007291 sp<FakeWindowHandle> window =
7292 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7293 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007294
7295 window->setDisableUserActivity(true);
7296 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007297 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00007298 setFocusedWindow(window);
7299
7300 window->consumeFocusEvent(true);
7301
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007302 mDispatcher->notifyKey(
7303 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00007304
7305 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007306 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007307
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007308 // Should have not poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00007309 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00007310 mFakePolicy->assertUserActivityNotPoked();
7311}
7312
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007313TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyConsumedKey) {
Josep del Riob3981622023-04-18 15:49:45 +00007314 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007315 sp<FakeWindowHandle> window =
7316 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7317 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007318
7319 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007320 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00007321 setFocusedWindow(window);
7322
7323 window->consumeFocusEvent(true);
7324
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007325 mFakePolicy->setConsumeKeyBeforeDispatching(true);
7326
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007327 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007328 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00007329 mDispatcher->waitForIdle();
7330
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007331 // Key is not passed down
Josep del Riob3981622023-04-18 15:49:45 +00007332 window->assertNoEvents();
7333
7334 // Should have poked user activity
7335 mFakePolicy->assertUserActivityPoked();
7336}
7337
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007338TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserActivity) {
Josep del Riob3981622023-04-18 15:49:45 +00007339 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007340 sp<FakeWindowHandle> window =
7341 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7342 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00007343
7344 window->setDisableUserActivity(true);
7345 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007346 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00007347 setFocusedWindow(window);
7348
7349 window->consumeFocusEvent(true);
7350
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007351 mFakePolicy->setConsumeKeyBeforeDispatching(true);
7352
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007353 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007354 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00007355 mDispatcher->waitForIdle();
7356
7357 // System key is not passed down
7358 window->assertNoEvents();
7359
7360 // Should have poked user activity
7361 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007362}
7363
Josep del Rioc8fdedb2024-05-21 13:32:43 +00007364class DisableUserActivityInputDispatcherTest : public InputDispatcherTest,
7365 public ::testing::WithParamInterface<bool> {};
7366
7367TEST_P(DisableUserActivityInputDispatcherTest, NotPassedToUserUserActivity) {
7368 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7369 sp<FakeWindowHandle> window =
7370 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7371 ui::LogicalDisplayId::DEFAULT);
7372
7373 window->setDisableUserActivity(GetParam());
7374
7375 window->setFocusable(true);
7376 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7377 setFocusedWindow(window);
7378
7379 window->consumeFocusEvent(true);
7380
7381 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
7382 .keyCode(AKEYCODE_A)
7383 .policyFlags(0)
7384 .build());
7385 mDispatcher->waitForIdle();
7386
7387 // Key is not passed down
7388 window->assertNoEvents();
7389
7390 // Should not have poked user activity
7391 mFakePolicy->assertUserActivityNotPoked();
7392}
7393
7394INSTANTIATE_TEST_CASE_P(DisableUserActivity, DisableUserActivityInputDispatcherTest,
7395 ::testing::Bool());
7396
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007397TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
7398 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007399 sp<FakeWindowHandle> window =
7400 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7401 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007402
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007403 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007404
7405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007406 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007407 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007408 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7409
7410 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007411 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007412
7413 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00007414 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07007415 mFakePolicy->assertUserActivityPoked();
7416}
7417
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007418TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007419 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007420 sp<FakeWindowHandle> window =
7421 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7422 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007423
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007424 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007425
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007426 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007427 mDispatcher->waitForIdle();
7428
7429 window->assertNoEvents();
7430}
7431
7432// If a window is touchable, but does not have focus, it should receive motion events, but not keys
7433TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07007434 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007435 sp<FakeWindowHandle> window =
7436 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7437 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007438
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007439 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007440
7441 // Send key
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007442 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007443 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00007444 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007445 AINPUT_SOURCE_TOUCHSCREEN,
7446 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007447
7448 // Window should receive only the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007449 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007450 window->assertNoEvents(); // Key event or focus event will not be received
7451}
7452
arthurhungea3f4fc2020-12-21 23:18:53 +08007453TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
7454 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7455
arthurhungea3f4fc2020-12-21 23:18:53 +08007456 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007457 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007458 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08007459 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08007460
arthurhungea3f4fc2020-12-21 23:18:53 +08007461 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007462 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007463 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08007464 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08007465
7466 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007467 mDispatcher->onWindowInfosChanged(
7468 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08007469
7470 PointF pointInFirst = {300, 200};
7471 PointF pointInSecond = {300, 600};
7472
7473 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007474 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007475 AINPUT_SOURCE_TOUCHSCREEN,
7476 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08007477 // Only the first window should get the down event
7478 firstWindow->consumeMotionDown();
7479 secondWindow->assertNoEvents();
7480
7481 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00007482 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007483 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00007484 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08007485 // The first window gets a move and the second a down
7486 firstWindow->consumeMotionMove();
7487 secondWindow->consumeMotionDown();
7488
7489 // Send pointer cancel to the second window
7490 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007491 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
7492 ui::LogicalDisplayId::DEFAULT, {pointInFirst, pointInSecond});
arthurhungea3f4fc2020-12-21 23:18:53 +08007493 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00007494 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08007495 // The first window gets move and the second gets cancel.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007496 firstWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
7497 secondWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
arthurhungea3f4fc2020-12-21 23:18:53 +08007498
7499 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00007500 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007501 ui::LogicalDisplayId::DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08007502 // The first window gets up and the second gets nothing.
7503 firstWindow->consumeMotionUp();
7504 secondWindow->assertNoEvents();
7505}
7506
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007507TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
7508 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7509
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007510 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
7511 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007512 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007513 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
7514 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
7515 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
7516
Harry Cutts33476232023-01-30 19:57:29 +00007517 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00007518 window->assertNoEvents();
7519 mDispatcher->waitForIdle();
7520}
7521
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007522using InputDispatcherMonitorTest = InputDispatcherTest;
7523
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007524/**
7525 * Two entities that receive touch: A window, and a global monitor.
7526 * The touch goes to the window, and then the window disappears.
7527 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
7528 * for the monitor, as well.
7529 * 1. foregroundWindow
7530 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
7531 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007532TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007533 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007534 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7535 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007536
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007537 FakeMonitorReceiver monitor =
7538 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007539
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007540 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007541 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007542 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7543 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007544 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7545
7546 // Both the foreground window and the global monitor should receive the touch down
7547 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007548 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007549
7550 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007551 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007552 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007553 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7554
7555 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007556 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007557
7558 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007559 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007560 window->consumeMotionCancel();
7561 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
7562
7563 // If more events come in, there will be no more foreground window to send them to. This will
7564 // cause a cancel for the monitor, as well.
7565 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007566 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007567 ui::LogicalDisplayId::DEFAULT, {120, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007568 << "Injection should fail because the window was removed";
7569 window->assertNoEvents();
7570 // Global monitor now gets the cancel
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007571 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007572}
7573
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007574TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07007575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007576 sp<FakeWindowHandle> window =
7577 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7578 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007579 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007580
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007581 FakeMonitorReceiver monitor =
7582 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007583
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007584 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007585 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7586 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007587 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007588 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7589 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007590}
7591
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007592TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007593 FakeMonitorReceiver monitor =
7594 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007595
Chris Yea209fde2020-07-22 13:54:51 -07007596 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007597 sp<FakeWindowHandle> window =
7598 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7599 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007600 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007601
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007602 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007603 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7604 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007605 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007606 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7607 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007608
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007609 // Pilfer pointers from the monitor.
7610 // This should not do anything and the window should continue to receive events.
7611 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00007612
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007613 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007614 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007615 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007616 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007617
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007618 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
7619 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007620}
7621
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007622TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07007623 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007624 sp<FakeWindowHandle> window =
7625 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7626 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007627 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07007628 window->setWindowOffset(20, 40);
7629 window->setWindowTransform(0, 1, -1, 0);
7630
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007631 FakeMonitorReceiver monitor =
7632 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07007633
7634 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007635 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7636 ui::LogicalDisplayId::DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07007637 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007638 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007639 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
7640 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07007641 // Even though window has transform, gesture monitor must not.
7642 ASSERT_EQ(ui::Transform(), event->getTransform());
7643}
7644
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007645TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00007646 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007647 FakeMonitorReceiver monitor =
7648 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00007649
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007650 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007651 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7652 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007653 << "Injection should fail if there is a monitor, but no touchable window";
7654 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00007655}
7656
Linnan Lid8150952024-01-26 18:07:17 +00007657/**
7658 * Two displays
7659 * The first monitor has a foreground window, a monitor
7660 * The second window has only one monitor.
7661 * We first inject a Down event into the first display, this injection should succeed and both
7662 * the foreground window and monitor should receive a down event, then inject a Down event into
7663 * the second display as well, this injection should fail, at this point, the first display
7664 * window and monitor should not receive a cancel or any other event.
7665 * Continue to inject Move and UP events to the first display, the events should be received
7666 * normally by the foreground window and monitor.
7667 */
7668TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
7669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007670 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7671 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007672
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007673 FakeMonitorReceiver monitor =
7674 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007675 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7676
7677 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007679 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7680 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007681 << "The down event injected into the first display should succeed";
7682
7683 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007684 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007685
7686 ASSERT_EQ(InputEventInjectionResult::FAILED,
7687 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7688 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007689 << "The down event injected into the second display should fail since there's no "
7690 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007691
7692 // Continue to inject event to first display.
7693 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7694 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007695 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007696 << "The move event injected into the first display should succeed";
7697
7698 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007699 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007700
7701 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007702 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007703 {110, 220}))
7704 << "The up event injected into the first display should succeed";
7705
7706 window->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007707 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007708
7709 window->assertNoEvents();
7710 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007711 secondMonitor.assertNoEvents();
7712}
7713
7714/**
7715 * Two displays
7716 * There is a monitor and foreground window on each display.
7717 * First, we inject down events into each of the two displays, at this point, the foreground windows
7718 * and monitors on both displays should receive down events.
7719 * At this point, the foreground window of the second display goes away, the gone window should
7720 * receive the cancel event, and the other windows and monitors should not receive any events.
7721 * Inject a move event into the second display. At this point, the injection should fail because
7722 * the second display no longer has a foreground window. At this point, the monitor on the second
7723 * display should receive a cancel event, and any windows or monitors on the first display should
7724 * not receive any events, and any subsequent injection of events into the second display should
7725 * also fail.
7726 * Continue to inject events into the first display, and the events should all be injected
7727 * successfully and received normally.
7728 */
7729TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
7730 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007731 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7732 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007733 sp<FakeWindowHandle> secondWindow =
7734 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
7735 SECOND_DISPLAY_ID);
7736
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007737 FakeMonitorReceiver monitor =
7738 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007739 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7740
7741 // There is a foreground window on both displays.
7742 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007744 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7745 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007746 << "The down event injected into the first display should succeed";
7747
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007748 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7749 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007750
7751 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7752 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7753 {100, 200}))
7754 << "The down event injected into the second display should succeed";
7755
Linnan Lid8150952024-01-26 18:07:17 +00007756 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
7757 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
7758
7759 // Now second window is gone away.
7760 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7761
7762 // The gone window should receive a cancel, and the monitor on the second display should not
7763 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00007764 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
7765 secondMonitor.assertNoEvents();
7766
7767 ASSERT_EQ(InputEventInjectionResult::FAILED,
7768 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7769 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007770 << "The move event injected into the second display should fail because there's no "
7771 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007772 // Now the monitor on the second display should receive a cancel event.
7773 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00007774
7775 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7776 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007777 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007778 << "The move event injected into the first display should succeed";
7779
7780 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007781 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007782
7783 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007784 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7785 {110, 220}))
7786 << "The up event injected into the second display should fail because there's no "
7787 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007788
7789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007790 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007791 {110, 220}))
7792 << "The up event injected into the first display should succeed";
7793
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007794 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
7795 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007796
Linnan Lid8150952024-01-26 18:07:17 +00007797 window->assertNoEvents();
7798 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007799 secondWindow->assertNoEvents();
7800 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007801}
7802
7803/**
7804 * One display with transform
7805 * There is a foreground window and a monitor on the display
7806 * Inject down event and move event sequentially, the foreground window and monitor can receive down
7807 * event and move event, then let the foreground window go away, the foreground window receives
7808 * cancel event, inject move event again, the monitor receives cancel event, all the events received
7809 * by the monitor should be with the same transform as the display
7810 */
7811TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
7812 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007813 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7814 ui::LogicalDisplayId::DEFAULT);
7815 FakeMonitorReceiver monitor =
7816 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007817
7818 ui::Transform transform;
7819 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7820
7821 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007822 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Linnan Lid8150952024-01-26 18:07:17 +00007823 displayInfo.transform = transform;
7824
7825 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
7826
7827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007828 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7829 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007830 << "The down event injected should succeed";
7831
7832 window->consumeMotionDown();
7833 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
7834 EXPECT_EQ(transform, downMotionEvent->getTransform());
7835 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
7836
7837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7838 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007839 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007840 << "The move event injected should succeed";
7841
7842 window->consumeMotionMove();
7843 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
7844 EXPECT_EQ(transform, moveMotionEvent->getTransform());
7845 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
7846
7847 // Let foreground window gone
7848 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
7849
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007850 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00007851 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00007852
7853 ASSERT_EQ(InputEventInjectionResult::FAILED,
7854 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007855 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007856 << "The move event injected should failed";
7857 // Now foreground should not receive any events, but monitor should receive a cancel event
7858 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00007859 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
7860 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007861 EXPECT_EQ(ui::LogicalDisplayId::DEFAULT, cancelMotionEvent->getDisplayId());
Linnan Lid8150952024-01-26 18:07:17 +00007862 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
7863
7864 // Other event inject to this display should fail.
7865 ASSERT_EQ(InputEventInjectionResult::FAILED,
7866 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007867 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007868 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00007869 window->assertNoEvents();
7870 monitor.assertNoEvents();
7871}
7872
chaviw81e2bb92019-12-18 15:03:51 -08007873TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007874 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007875 sp<FakeWindowHandle> window =
7876 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7877 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007878
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007879 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08007880
7881 NotifyMotionArgs motionArgs =
7882 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007883 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007884
Prabir Pradhan678438e2023-04-13 19:32:51 +00007885 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08007886 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007887 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007888
7889 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08007890 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08007891 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7892 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
7893 motionArgs.pointerCoords[0].getX() - 10);
7894
Prabir Pradhan678438e2023-04-13 19:32:51 +00007895 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007896 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08007897}
7898
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007899/**
7900 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
7901 * the device default right away. In the test scenario, we check both the default value,
7902 * and the action of enabling / disabling.
7903 */
7904TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07007905 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007906 sp<FakeWindowHandle> window =
7907 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7908 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08007909 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007910
7911 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007912 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007913 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007914
7915 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007916 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007917 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007918 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007919
7920 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007921 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007922 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007923 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007924
7925 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007926 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007927 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007928 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07007929 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007930 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007931 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007932 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007933
7934 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007935 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007936 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007937 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007938
7939 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007940 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007941 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007942 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07007943 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007944 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007945 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007946 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007947
7948 window->assertNoEvents();
7949}
7950
Gang Wange9087892020-01-07 12:17:14 -05007951TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007952 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007953 sp<FakeWindowHandle> window =
7954 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7955 ui::LogicalDisplayId::DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05007956
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007957 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007958 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05007959
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007960 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007961 setFocusedWindow(window);
7962
Harry Cutts33476232023-01-30 19:57:29 +00007963 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05007964
Prabir Pradhan678438e2023-04-13 19:32:51 +00007965 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
7966 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05007967
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007968 std::unique_ptr<KeyEvent> event = window->consumeKey();
7969 ASSERT_NE(event, nullptr);
7970 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05007971 ASSERT_NE(verified, nullptr);
7972 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
7973
7974 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
7975 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
7976 ASSERT_EQ(keyArgs.source, verified->source);
7977 ASSERT_EQ(keyArgs.displayId, verified->displayId);
7978
7979 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
7980
7981 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05007982 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007983 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05007984 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
7985 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
7986 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
7987 ASSERT_EQ(0, verifiedKey.repeatCount);
7988}
7989
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007990TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007991 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007992 sp<FakeWindowHandle> window =
7993 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7994 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007995
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007996 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007997
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007998 ui::Transform transform;
7999 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
8000
8001 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008002 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07008003 displayInfo.transform = transform;
8004
Patrick Williamsd828f302023-04-28 17:52:08 -05008005 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008006
Prabir Pradhan678438e2023-04-13 19:32:51 +00008007 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008008 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008009 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008010 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008011
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008012 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
8013 ASSERT_NE(nullptr, event);
8014 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008015 ASSERT_NE(verified, nullptr);
8016 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
8017
8018 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
8019 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
8020 EXPECT_EQ(motionArgs.source, verified->source);
8021 EXPECT_EQ(motionArgs.displayId, verified->displayId);
8022
8023 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
8024
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07008025 const vec2 rawXY =
8026 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
8027 motionArgs.pointerCoords[0].getXYValue());
8028 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
8029 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008030 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008031 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08008032 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08008033 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
8034 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
8035}
8036
chaviw09c8d2d2020-08-24 15:48:26 -07008037/**
8038 * Ensure that separate calls to sign the same data are generating the same key.
8039 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
8040 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
8041 * tests.
8042 */
8043TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
8044 KeyEvent event = getTestKeyEvent();
8045 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
8046
8047 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
8048 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
8049 ASSERT_EQ(hmac1, hmac2);
8050}
8051
8052/**
8053 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
8054 */
8055TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
8056 KeyEvent event = getTestKeyEvent();
8057 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
8058 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
8059
8060 verifiedEvent.deviceId += 1;
8061 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8062
8063 verifiedEvent.source += 1;
8064 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8065
8066 verifiedEvent.eventTimeNanos += 1;
8067 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8068
Linnan Li13bf76a2024-05-05 19:18:02 +08008069 verifiedEvent.displayId = ui::LogicalDisplayId{verifiedEvent.displayId.val() + 1};
chaviw09c8d2d2020-08-24 15:48:26 -07008070 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8071
8072 verifiedEvent.action += 1;
8073 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8074
8075 verifiedEvent.downTimeNanos += 1;
8076 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8077
8078 verifiedEvent.flags += 1;
8079 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8080
8081 verifiedEvent.keyCode += 1;
8082 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8083
8084 verifiedEvent.scanCode += 1;
8085 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8086
8087 verifiedEvent.metaState += 1;
8088 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8089
8090 verifiedEvent.repeatCount += 1;
8091 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
8092}
8093
Vishnu Nair958da932020-08-21 17:12:37 -07008094TEST_F(InputDispatcherTest, SetFocusedWindow) {
8095 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008096 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8097 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008098 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008099 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8100 ui::LogicalDisplayId::DEFAULT);
8101 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008102
8103 // Top window is also focusable but is not granted focus.
8104 windowTop->setFocusable(true);
8105 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008106 mDispatcher->onWindowInfosChanged(
8107 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008108 setFocusedWindow(windowSecond);
8109
8110 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008111 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008112 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008113
8114 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008115 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07008116 windowTop->assertNoEvents();
8117}
8118
8119TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
8120 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008121 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8122 ui::LogicalDisplayId::DEFAULT);
8123 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008124
8125 window->setFocusable(true);
8126 // Release channel for window is no longer valid.
8127 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008128 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008129 setFocusedWindow(window);
8130
8131 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008132 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07008133
8134 // window channel is invalid, so it should not receive any input event.
8135 window->assertNoEvents();
8136}
8137
8138TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
8139 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008140 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8141 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008142 window->setFocusable(false);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008143 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008144
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008145 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008146 setFocusedWindow(window);
8147
8148 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008149 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07008150
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08008151 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07008152 window->assertNoEvents();
8153}
8154
8155TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
8156 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008157 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8158 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008159 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008160 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8161 ui::LogicalDisplayId::DEFAULT);
8162 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008163
8164 windowTop->setFocusable(true);
8165 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008166 mDispatcher->onWindowInfosChanged(
8167 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008168 setFocusedWindow(windowTop);
8169 windowTop->consumeFocusEvent(true);
8170
Chavi Weingarten847e8512023-03-29 00:26:09 +00008171 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008172 mDispatcher->onWindowInfosChanged(
8173 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008174 windowSecond->consumeFocusEvent(true);
8175 windowTop->consumeFocusEvent(false);
8176
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008177 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008178 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008179
8180 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008181 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07008182}
8183
Chavi Weingarten847e8512023-03-29 00:26:09 +00008184TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07008185 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008186 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8187 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008188 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008189 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8190 ui::LogicalDisplayId::DEFAULT);
8191 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008192
8193 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00008194 windowSecond->setFocusable(false);
8195 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008196 mDispatcher->onWindowInfosChanged(
8197 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00008198 setFocusedWindow(windowTop);
8199 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07008200
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008201 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00008202 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008203
8204 // Event should be dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008205 windowTop->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07008206 windowSecond->assertNoEvents();
8207}
8208
8209TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
8210 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008211 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
8212 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008213 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008214 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008215 ui::LogicalDisplayId::DEFAULT);
8216 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07008217
8218 window->setFocusable(true);
8219 previousFocusedWindow->setFocusable(true);
8220 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008221 mDispatcher->onWindowInfosChanged(
8222 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008223 setFocusedWindow(previousFocusedWindow);
8224 previousFocusedWindow->consumeFocusEvent(true);
8225
8226 // Requesting focus on invisible window takes focus from currently focused window.
8227 setFocusedWindow(window);
8228 previousFocusedWindow->consumeFocusEvent(false);
8229
8230 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008231 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008232 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008233 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07008234
8235 // Window does not get focus event or key down.
8236 window->assertNoEvents();
8237
8238 // Window becomes visible.
8239 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008240 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008241
8242 // Window receives focus event.
8243 window->consumeFocusEvent(true);
8244 // Focused window receives key down.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008245 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008246}
8247
Vishnu Nair599f1412021-06-21 10:39:58 -07008248TEST_F(InputDispatcherTest, DisplayRemoved) {
8249 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008250 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "window",
8251 ui::LogicalDisplayId::DEFAULT);
8252 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair599f1412021-06-21 10:39:58 -07008253
8254 // window is granted focus.
8255 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008256 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07008257 setFocusedWindow(window);
8258 window->consumeFocusEvent(true);
8259
8260 // When a display is removed window loses focus.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008261 mDispatcher->displayRemoved(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07008262 window->consumeFocusEvent(false);
8263}
8264
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008265/**
8266 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
8267 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
8268 * of the 'slipperyEnterWindow'.
8269 *
8270 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
8271 * a way so that the touched location is no longer covered by the top window.
8272 *
8273 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
8274 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
8275 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
8276 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
8277 * with ACTION_DOWN).
8278 * Thus, the touch has been transferred from the top window into the bottom window, because the top
8279 * window moved itself away from the touched location and had Flag::SLIPPERY.
8280 *
8281 * Even though the top window moved away from the touched location, it is still obscuring the bottom
8282 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
8283 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
8284 *
8285 * In this test, we ensure that the event received by the bottom window has
8286 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
8287 */
8288TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008289 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008290 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008291
8292 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008293 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008294
8295 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008296 sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
8297 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08008298 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008299 // Make sure this one overlaps the bottom window
8300 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
8301 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
8302 // one. Windows with the same owner are not considered to be occluding each other.
8303 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
8304
8305 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008306 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
8307 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008308 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
8309
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008310 mDispatcher->onWindowInfosChanged(
8311 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008312
8313 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00008314 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008315 AINPUT_SOURCE_TOUCHSCREEN,
8316 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008317 slipperyExitWindow->consumeMotionDown();
8318 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008319 mDispatcher->onWindowInfosChanged(
8320 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008321
Prabir Pradhan678438e2023-04-13 19:32:51 +00008322 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008323 AINPUT_SOURCE_TOUCHSCREEN,
8324 ui::LogicalDisplayId::DEFAULT, {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008325
8326 slipperyExitWindow->consumeMotionCancel();
8327
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008328 slipperyEnterWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008329 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
8330}
8331
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008332/**
8333 * Two windows, one on the left and another on the right. The left window is slippery. The right
8334 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
8335 * touch moves from the left window into the right window, the gesture should continue to go to the
8336 * left window. Touch shouldn't slip because the right window can't receive touches. This test
8337 * reproduces a crash.
8338 */
8339TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
8340 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8341
8342 sp<FakeWindowHandle> leftSlipperyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008343 sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
8344 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008345 leftSlipperyWindow->setSlippery(true);
8346 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
8347
8348 sp<FakeWindowHandle> rightDropTouchesWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008349 sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
8350 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008351 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
8352 rightDropTouchesWindow->setDropInput(true);
8353
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008354 mDispatcher->onWindowInfosChanged(
8355 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07008356
8357 // Start touch in the left window
8358 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8359 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8360 .build());
8361 leftSlipperyWindow->consumeMotionDown();
8362
8363 // And move it into the right window
8364 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8365 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8366 .build());
8367
8368 // Since the right window isn't eligible to receive input, touch does not slip.
8369 // The left window continues to receive the gesture.
8370 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
8371 rightDropTouchesWindow->assertNoEvents();
8372}
8373
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008374/**
8375 * A single window is on screen first. Touch is injected into that window. Next, a second window
8376 * appears. Since the first window is slippery, touch will move from the first window to the second.
8377 */
8378TEST_F(InputDispatcherTest, InjectedTouchSlips) {
8379 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8380 sp<FakeWindowHandle> originalWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008381 sp<FakeWindowHandle>::make(application, mDispatcher, "Original",
8382 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008383 originalWindow->setFrame(Rect(0, 0, 200, 200));
8384 originalWindow->setSlippery(true);
8385
8386 sp<FakeWindowHandle> appearingWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008387 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing",
8388 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07008389 appearingWindow->setFrame(Rect(0, 0, 200, 200));
8390
8391 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
8392
8393 // Touch down on the original window
8394 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8395 injectMotionEvent(*mDispatcher,
8396 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8397 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
8398 .build()));
8399 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8400
8401 // Now, a new window appears. This could be, for example, a notification shade that appears
8402 // after user starts to drag down on the launcher window.
8403 mDispatcher->onWindowInfosChanged(
8404 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
8405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8406 injectMotionEvent(*mDispatcher,
8407 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8408 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
8409 .build()));
8410 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
8411 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
8412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
8413 injectMotionEvent(*mDispatcher,
8414 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8415 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
8416 .build()));
8417 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
8418
8419 originalWindow->assertNoEvents();
8420 appearingWindow->assertNoEvents();
8421}
8422
Linnan Li49b2b202024-04-12 12:46:40 +08008423/**
8424 * Three windows:
8425 * - left window, which has FLAG_SLIPPERY, so it supports slippery exit
8426 * - right window
8427 * - spy window
8428 * The three windows do not overlap.
8429 *
8430 * We have two devices reporting events:
8431 * - Device A reports ACTION_DOWN, which lands in the left window
8432 * - Device B reports ACTION_DOWN, which lands in the spy window.
8433 * - Now, device B reports ACTION_MOVE events which move to the right window.
8434 *
8435 * The right window should not receive any events because the spy window is not a foreground window,
8436 * and also it does not support slippery touches.
8437 */
8438TEST_F(InputDispatcherTest, MultiDeviceSpyWindowSlipTest) {
8439 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8440 sp<FakeWindowHandle> leftWindow =
8441 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008442 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008443 leftWindow->setFrame(Rect(0, 0, 100, 100));
8444 leftWindow->setSlippery(true);
8445
8446 sp<FakeWindowHandle> rightWindow =
8447 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008448 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008449 rightWindow->setFrame(Rect(100, 0, 200, 100));
8450
8451 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008452 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8453 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008454 spyWindow->setFrame(Rect(200, 0, 300, 100));
8455 spyWindow->setSpy(true);
8456 spyWindow->setTrustedOverlay(true);
8457
8458 mDispatcher->onWindowInfosChanged(
8459 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *spyWindow->getInfo()}, {}, 0, 0});
8460
8461 const DeviceId deviceA = 9;
8462 const DeviceId deviceB = 3;
8463
8464 // Tap on left window with device A
8465 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8466 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8467 .deviceId(deviceA)
8468 .build());
8469 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8470
8471 // Tap on spy window with device B
8472 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8473 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
8474 .deviceId(deviceB)
8475 .build());
8476 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8477
8478 // Move to right window with device B. Touches should not slip to the right window, because spy
8479 // window is not a foreground window, and it does not have FLAG_SLIPPERY
8480 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8481 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8482 .deviceId(deviceB)
8483 .build());
8484 leftWindow->assertNoEvents();
8485 rightWindow->assertNoEvents();
8486 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
8487}
8488
8489/**
8490 * Three windows arranged horizontally and without any overlap.
8491 * The left and right windows have FLAG_SLIPPERY. The middle window does not have any special flags.
8492 *
8493 * We have two devices reporting events:
8494 * - Device A reports ACTION_DOWN which lands in the left window
8495 * - Device B reports ACTION_DOWN which lands in the right window
8496 * - Device B reports ACTION_MOVE that shifts to the middle window.
8497 * This should cause touches for Device B to slip from the right window to the middle window.
8498 * The right window should receive ACTION_CANCEL for device B and the
8499 * middle window should receive down event for Device B.
8500 * If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
8501 */
8502TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
Siarhei Vishniakoudd56df12024-05-20 14:56:38 -07008503 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
Linnan Li49b2b202024-04-12 12:46:40 +08008504 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8505 sp<FakeWindowHandle> leftWindow =
8506 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008507 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008508 leftWindow->setFrame(Rect(0, 0, 100, 100));
8509 leftWindow->setSlippery(true);
8510
8511 sp<FakeWindowHandle> middleWindow =
8512 sp<FakeWindowHandle>::make(application, mDispatcher, "middle window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008513 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008514 middleWindow->setFrame(Rect(100, 0, 200, 100));
8515
8516 sp<FakeWindowHandle> rightWindow =
8517 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008518 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08008519 rightWindow->setFrame(Rect(200, 0, 300, 100));
8520 rightWindow->setSlippery(true);
8521
8522 mDispatcher->onWindowInfosChanged(
8523 {{*leftWindow->getInfo(), *middleWindow->getInfo(), *rightWindow->getInfo()},
8524 {},
8525 0,
8526 0});
8527
8528 const DeviceId deviceA = 9;
8529 const DeviceId deviceB = 3;
8530
8531 // Tap on left window with device A
8532 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8533 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8534 .deviceId(deviceA)
8535 .build());
8536 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8537
8538 // Tap on right window with device B
8539 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8540 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
8541 .deviceId(deviceB)
8542 .build());
8543 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8544
8545 // Move to middle window with device B. Touches should slip to middle window, because right
8546 // window is a foreground window that's associated with device B and has FLAG_SLIPPERY.
8547 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8548 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8549 .deviceId(deviceB)
8550 .build());
8551 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
8552 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8553
8554 // Move to middle window with device A. Touches should slip to middle window, because left
8555 // window is a foreground window that's associated with device A and has FLAG_SLIPPERY.
8556 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8557 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8558 .deviceId(deviceA)
8559 .build());
8560 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceA)));
8561 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8562
8563 // Ensure that middle window can receive the remaining move events.
8564 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8565 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
8566 .deviceId(deviceB)
8567 .build());
8568 leftWindow->assertNoEvents();
8569 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
8570 rightWindow->assertNoEvents();
8571}
8572
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008573TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008574 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8576
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008577 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
8578 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008579 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008580 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008581
8582 sp<FakeWindowHandle> rightSpy =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008583 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy",
8584 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008585 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008586 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008587 rightSpy->setSpy(true);
8588 rightSpy->setTrustedOverlay(true);
8589
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008590 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
8591 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008592 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008593 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008594
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008595 mDispatcher->onWindowInfosChanged(
8596 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008597
8598 // Touch in the left window
8599 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8600 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8601 .build());
8602 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
8603 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008604 ASSERT_NO_FATAL_FAILURE(
8605 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008606
8607 // Touch another finger over the right windows
8608 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8609 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8610 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8611 .build());
8612 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
8613 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
8614 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
8615 mDispatcher->waitForIdle();
8616 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008617 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
8618 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008619
8620 // Release finger over left window. The UP actions are not treated as device interaction.
8621 // The windows that did not receive the UP pointer will receive MOVE events, but since this
8622 // is part of the UP action, we do not treat this as device interaction.
8623 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
8624 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8625 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8626 .build());
8627 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
8628 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8629 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8630 mDispatcher->waitForIdle();
8631 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8632
8633 // Move remaining finger
8634 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8635 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8636 .build());
8637 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8638 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8639 mDispatcher->waitForIdle();
8640 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008641 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008642
8643 // Release all fingers
8644 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8645 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8646 .build());
8647 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
8648 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
8649 mDispatcher->waitForIdle();
8650 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8651}
8652
8653TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
8654 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8655
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008656 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8657 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008658 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008659 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008660
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008661 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008662 setFocusedWindow(window);
8663 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
8664
8665 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008666 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008667 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008668 ASSERT_NO_FATAL_FAILURE(
8669 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008670
8671 // The UP actions are not treated as device interaction.
8672 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008673 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008674 mDispatcher->waitForIdle();
8675 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8676}
8677
Prabir Pradhan5893d362023-11-17 04:30:40 +00008678TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
8679 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8680
8681 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008682 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008683 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008684 sp<FakeWindowHandle> right =
8685 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
8686 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008687 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008688 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8689 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008690 spy->setFrame(Rect(0, 0, 200, 100));
8691 spy->setTrustedOverlay(true);
8692 spy->setSpy(true);
8693
8694 mDispatcher->onWindowInfosChanged(
8695 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
8696
8697 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008698 NotifyMotionArgs notifyArgs =
8699 generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8700 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008701 mDispatcher->notifyMotion(notifyArgs);
8702
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008703 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008704 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
8705 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008706 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008707 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8708 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008709 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008710 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8711
8712 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008713 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8714 ui::LogicalDisplayId::DEFAULT, {PointF{150, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008715 mDispatcher->notifyMotion(notifyArgs);
8716
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008717 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008718 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
8719 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008720 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008721 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8722 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008723 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008724 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8725
8726 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
8727}
8728
Linnan Liccf6ce32024-04-11 20:32:13 +08008729/**
8730 * When a device reports a DOWN event, which lands in a window that supports splits, and then the
8731 * device then reports a POINTER_DOWN, which lands in the location of a non-existing window, then
8732 * the previous window should receive this event and not be dropped.
8733 */
8734TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
Siarhei Vishniakoua3fe6642024-07-18 11:58:25 -07008735 SCOPED_FLAG_OVERRIDE(split_all_touches, false);
Linnan Liccf6ce32024-04-11 20:32:13 +08008736 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008737 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8738 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008739 window->setFrame(Rect(0, 0, 100, 100));
8740 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8741
8742 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8743 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8744 .build());
8745
8746 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
8747
8748 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8749 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8750 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
8751 .build());
8752
8753 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_1_DOWN)));
8754}
8755
8756/**
8757 * When deviceA reports a DOWN event, which lands in a window that supports splits, and then deviceB
8758 * also reports a DOWN event, which lands in the location of a non-existing window, then the
8759 * previous window should receive deviceB's event and it should be dropped.
8760 */
8761TEST_F(InputDispatcherMultiDeviceTest, SecondDeviceDownEventDroppedWithoutWindowTarget) {
8762 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008763 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8764 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008765 window->setFrame(Rect(0, 0, 100, 100));
8766 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8767
8768 const DeviceId deviceA = 9;
8769 const DeviceId deviceB = 3;
8770
8771 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8772 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8773 .deviceId(deviceA)
8774 .build());
8775 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8776
8777 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8778 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
8779 .deviceId(deviceB)
8780 .build());
8781 window->assertNoEvents();
8782}
8783
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008784class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
8785protected:
8786 std::shared_ptr<FakeApplicationHandle> mApp;
8787 sp<FakeWindowHandle> mWindow;
8788
8789 virtual void SetUp() override {
8790 InputDispatcherTest::SetUp();
8791
8792 mApp = std::make_shared<FakeApplicationHandle>();
8793
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008794 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window",
8795 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008796 mWindow->setFrame(Rect(0, 0, 100, 100));
8797
8798 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8799 setFocusedWindow(mWindow);
8800 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
8801 }
8802
8803 void setFallback(int32_t keycode) {
8804 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
8805 return KeyEventBuilder(event).keyCode(keycode).build();
8806 });
8807 }
8808
8809 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008810 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
8811 ASSERT_NE(nullptr, event);
8812 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008813 }
8814};
8815
8816TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
8817 mDispatcher->notifyKey(
8818 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8819 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8820 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8821}
8822
8823TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
8824 mDispatcher->notifyKey(
8825 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8826 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8827 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8828}
8829
8830TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
8831 mDispatcher->notifyKey(
8832 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8833
8834 // Do not handle this key event.
8835 consumeKey(/*handled=*/false,
8836 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8837 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8838
8839 // Since the policy did not request any fallback to be generated, ensure there are no events.
8840 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8841}
8842
8843TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
8844 setFallback(AKEYCODE_B);
8845 mDispatcher->notifyKey(
8846 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8847
8848 // Do not handle this key event.
8849 consumeKey(/*handled=*/false,
8850 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8851
8852 // Since the key was not handled, ensure the fallback event was dispatched instead.
8853 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8854 consumeKey(/*handled=*/true,
8855 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8856 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8857
8858 // Release the original key, and ensure the fallback key is also released.
8859 mDispatcher->notifyKey(
8860 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8861 consumeKey(/*handled=*/false,
8862 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8863 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8864 consumeKey(/*handled=*/true,
8865 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8866 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8867
8868 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8869 mWindow->assertNoEvents();
8870}
8871
8872TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
8873 setFallback(AKEYCODE_B);
8874 mDispatcher->notifyKey(
8875 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8876
8877 // Do not handle this key event, but handle the fallback.
8878 consumeKey(/*handled=*/false,
8879 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8880 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8881 consumeKey(/*handled=*/true,
8882 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8883 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8884
8885 // Release the original key, and ensure the fallback key is also released.
8886 mDispatcher->notifyKey(
8887 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8888 // But this time, the app handles the original key.
8889 consumeKey(/*handled=*/true,
8890 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8891 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8892 // Ensure the fallback key is canceled.
8893 consumeKey(/*handled=*/true,
8894 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8895 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8896
8897 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8898 mWindow->assertNoEvents();
8899}
8900
8901TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
8902 setFallback(AKEYCODE_B);
8903 mDispatcher->notifyKey(
8904 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8905
8906 // Do not handle this key event.
8907 consumeKey(/*handled=*/false,
8908 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8909 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8910 // App does not handle the fallback either, so ensure another fallback is not generated.
8911 setFallback(AKEYCODE_C);
8912 consumeKey(/*handled=*/false,
8913 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8914 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8915
8916 // Release the original key, and ensure the fallback key is also released.
8917 setFallback(AKEYCODE_B);
8918 mDispatcher->notifyKey(
8919 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8920 consumeKey(/*handled=*/false,
8921 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8922 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8923 consumeKey(/*handled=*/false,
8924 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8925 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8926
8927 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8928 mWindow->assertNoEvents();
8929}
8930
8931TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
8932 setFallback(AKEYCODE_B);
8933 mDispatcher->notifyKey(
8934 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8935
8936 // Do not handle this key event, so fallback is generated.
8937 consumeKey(/*handled=*/false,
8938 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8939 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8940 consumeKey(/*handled=*/true,
8941 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8942 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8943
8944 // Release the original key, but assume the policy is misbehaving and it
8945 // generates an inconsistent fallback to the one from the DOWN event.
8946 setFallback(AKEYCODE_C);
8947 mDispatcher->notifyKey(
8948 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8949 consumeKey(/*handled=*/false,
8950 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8951 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8952 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
8953 consumeKey(/*handled=*/true,
8954 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8955 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8956
8957 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8958 mWindow->assertNoEvents();
8959}
8960
8961TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
8962 setFallback(AKEYCODE_B);
8963 mDispatcher->notifyKey(
8964 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8965
8966 // Do not handle this key event, so fallback is generated.
8967 consumeKey(/*handled=*/false,
8968 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8969 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8970 consumeKey(/*handled=*/true,
8971 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8972 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8973
8974 // The original key is canceled.
8975 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
8976 .keyCode(AKEYCODE_A)
8977 .addFlag(AKEY_EVENT_FLAG_CANCELED)
8978 .build());
8979 consumeKey(/*handled=*/false,
8980 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8981 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8982 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8983 // Ensure the fallback key is also canceled due to the original key being canceled.
8984 consumeKey(/*handled=*/true,
8985 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8986 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8987
8988 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8989 mWindow->assertNoEvents();
8990}
8991
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008992TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00008993 setFallback(AKEYCODE_B);
8994 mDispatcher->notifyKey(
8995 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8996
8997 // Do not handle this key event.
8998 consumeKey(/*handled=*/false,
8999 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9000 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9001 consumeKey(/*handled=*/true,
9002 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9003 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9004
9005 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
9006 // When the unhandled key is reported to the policy next, remove the input channel.
9007 mDispatcher->removeInputChannel(mWindow->getToken());
9008 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
9009 });
9010 // Release the original key, and let the app now handle the previously unhandled key.
9011 // This should result in the previously generated fallback key to be cancelled.
9012 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
9013 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
9014 // without holding the lock, because it need to synchronously fetch the fallback key. While in
9015 // the policy call, we will now remove the input channel. Once the policy call returns, the
9016 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
9017 // not cause any crashes.
9018 mDispatcher->notifyKey(
9019 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9020 consumeKey(/*handled=*/true,
9021 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9022 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9023}
9024
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00009025TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
9026 setFallback(AKEYCODE_B);
9027 mDispatcher->notifyKey(
9028 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9029
9030 // Do not handle this key event.
9031 consumeKey(/*handled=*/false,
9032 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9033 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9034 consumeKey(/*handled=*/true,
9035 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9036 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9037
9038 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
9039 // When the unhandled key is reported to the policy next, remove the window.
9040 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9041 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
9042 });
9043 // Release the original key, which the app will not handle. When this unhandled key is reported
9044 // to the policy, the window will be removed.
9045 mDispatcher->notifyKey(
9046 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9047 consumeKey(/*handled=*/false,
9048 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9049 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9050
9051 // Since the window was removed, it loses focus, and the channel state will be reset.
9052 consumeKey(/*handled=*/true,
9053 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9054 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9055 mWindow->consumeFocusEvent(false);
9056 mWindow->assertNoEvents();
9057}
9058
9059TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
9060 setFallback(AKEYCODE_B);
9061 mDispatcher->notifyKey(
9062 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
9063
9064 // Do not handle this key event.
9065 consumeKey(/*handled=*/false,
9066 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
9067 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
9068 const auto [seq, event] = mWindow->receiveEvent();
9069 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
9070 ASSERT_EQ(event->getType(), InputEventType::KEY);
9071 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
9072 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
9073 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
9074
9075 // Remove the window now, which should generate a cancellations and make the window lose focus.
9076 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
9077 consumeKey(/*handled=*/true,
9078 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
9079 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
9080 consumeKey(/*handled=*/true,
9081 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
9082 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
9083 mWindow->consumeFocusEvent(false);
9084
9085 // Finish the event by reporting it as handled.
9086 mWindow->finishEvent(*seq);
9087 mWindow->assertNoEvents();
9088}
9089
Garfield Tan1c7bc862020-01-28 13:24:04 -08009090class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
9091protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08009092 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
9093 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Asmita Poddar2808d7e2024-09-12 13:15:38 +00009094 static constexpr bool KEY_REPEAT_ENABLED = true;
Garfield Tan1c7bc862020-01-28 13:24:04 -08009095
Chris Yea209fde2020-07-22 13:54:51 -07009096 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08009097 sp<FakeWindowHandle> mWindow;
9098
9099 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00009100 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08009101
Asmita Poddar2808d7e2024-09-12 13:15:38 +00009102 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY,
9103 KEY_REPEAT_ENABLED);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009104 setUpWindow();
9105 }
9106
9107 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07009108 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009109 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window",
9110 ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009111
Vishnu Nair47074b82020-08-14 11:54:47 -07009112 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009113 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009114 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009115 mWindow->consumeFocusEvent(true);
9116 }
9117
Chris Ye2ad95392020-09-01 13:44:44 -07009118 void sendAndConsumeKeyDown(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009119 NotifyKeyArgs keyArgs =
9120 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07009121 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08009122 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00009123 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009124
9125 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009126 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009127 }
9128
9129 void expectKeyRepeatOnce(int32_t repeatCount) {
9130 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009131 mWindow->consumeKeyEvent(
9132 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08009133 }
9134
Chris Ye2ad95392020-09-01 13:44:44 -07009135 void sendAndConsumeKeyUp(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009136 NotifyKeyArgs keyArgs =
9137 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07009138 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08009139 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00009140 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009141
9142 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009143 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00009144 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009145 }
Hu Guofe3c8f12023-09-22 17:20:15 +08009146
9147 void injectKeyRepeat(int32_t repeatCount) {
9148 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009149 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount,
9150 ui::LogicalDisplayId::DEFAULT))
Hu Guofe3c8f12023-09-22 17:20:15 +08009151 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
9152 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08009153};
9154
9155TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00009156 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009157 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9158 expectKeyRepeatOnce(repeatCount);
9159 }
9160}
9161
9162TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00009163 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009164 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9165 expectKeyRepeatOnce(repeatCount);
9166 }
Harry Cutts33476232023-01-30 19:57:29 +00009167 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07009168 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08009169 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
9170 expectKeyRepeatOnce(repeatCount);
9171 }
9172}
9173
9174TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00009175 sendAndConsumeKeyDown(/*deviceId=*/1);
9176 expectKeyRepeatOnce(/*repeatCount=*/1);
9177 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009178 mWindow->assertNoEvents();
9179}
9180
9181TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00009182 sendAndConsumeKeyDown(/*deviceId=*/1);
9183 expectKeyRepeatOnce(/*repeatCount=*/1);
9184 sendAndConsumeKeyDown(/*deviceId=*/2);
9185 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009186 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00009187 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009188 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00009189 expectKeyRepeatOnce(/*repeatCount=*/2);
9190 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07009191 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00009192 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07009193 mWindow->assertNoEvents();
9194}
9195
9196TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00009197 sendAndConsumeKeyDown(/*deviceId=*/1);
9198 expectKeyRepeatOnce(/*repeatCount=*/1);
9199 sendAndConsumeKeyDown(/*deviceId=*/2);
9200 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07009201 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00009202 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07009203 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08009204 mWindow->assertNoEvents();
9205}
9206
liushenxiang42232912021-05-21 20:24:09 +08009207TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
9208 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00009209 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009210 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009211 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
liushenxiang42232912021-05-21 20:24:09 +08009212 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
9213 mWindow->assertNoEvents();
9214}
9215
Garfield Tan1c7bc862020-01-28 13:24:04 -08009216TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00009217 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00009218 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009219 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009220 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
9221 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009222 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009223 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08009224 }
9225}
9226
9227TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00009228 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00009229 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08009230
9231 std::unordered_set<int32_t> idSet;
9232 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009233 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
9234 ASSERT_NE(nullptr, repeatEvent);
9235 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08009236 EXPECT_EQ(idSet.end(), idSet.find(id));
9237 idSet.insert(id);
9238 }
9239}
9240
Hu Guofe3c8f12023-09-22 17:20:15 +08009241TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
9242 injectKeyRepeat(0);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009243 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Hu Guofe3c8f12023-09-22 17:20:15 +08009244 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
9245 expectKeyRepeatOnce(repeatCount);
9246 }
9247 injectKeyRepeat(1);
9248 // Expect repeatCount to be 3 instead of 1
9249 expectKeyRepeatOnce(3);
9250}
9251
Asmita Poddar2808d7e2024-09-12 13:15:38 +00009252TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_NoRepeatWhenKeyRepeatDisabled) {
9253 SCOPED_FLAG_OVERRIDE(keyboard_repeat_keys, true);
9254 static constexpr std::chrono::milliseconds KEY_NO_REPEAT_ASSERTION_TIMEOUT = 100ms;
9255
9256 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY,
9257 /*repeatKeyEnabled=*/false);
9258 sendAndConsumeKeyDown(/*deviceId=*/1);
9259
9260 ASSERT_GT(KEY_NO_REPEAT_ASSERTION_TIMEOUT, KEY_REPEAT_TIMEOUT)
9261 << "Ensure the check for no key repeats extends beyond the repeat timeout duration.";
9262 ASSERT_GT(KEY_NO_REPEAT_ASSERTION_TIMEOUT, KEY_REPEAT_DELAY)
9263 << "Ensure the check for no key repeats extends beyond the repeat delay duration.";
9264
9265 // No events should be returned if key repeat is turned off.
9266 // Wait for KEY_NO_REPEAT_ASSERTION_TIMEOUT to return no events to ensure key repeat disabled.
9267 mWindow->assertNoEvents(KEY_NO_REPEAT_ASSERTION_TIMEOUT);
9268}
9269
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009270/* Test InputDispatcher for MultiDisplay */
9271class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
9272public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009273 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009274 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08009275
Chris Yea209fde2020-07-22 13:54:51 -07009276 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009277 windowInPrimary = sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1",
9278 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009279
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009280 // Set focus window for primary display, but focused display would be second one.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009281 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07009282 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009283 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
9284
Vishnu Nair958da932020-08-21 17:12:37 -07009285 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009286 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08009287
Chris Yea209fde2020-07-22 13:54:51 -07009288 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009289 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009290 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009291 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009292 // Set focus display to second one.
9293 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +00009294 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
9295
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009296 // Set focus window for second display.
9297 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07009298 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009299 mDispatcher->onWindowInfosChanged(
9300 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009301 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009302 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009303 }
9304
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009305 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009306 InputDispatcherTest::TearDown();
9307
Chris Yea209fde2020-07-22 13:54:51 -07009308 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009309 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07009310 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009311 windowInSecondary.clear();
9312 }
9313
9314protected:
Chris Yea209fde2020-07-22 13:54:51 -07009315 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009316 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07009317 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009318 sp<FakeWindowHandle> windowInSecondary;
9319};
9320
9321TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
9322 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009323 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009324 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9325 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009326 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009327 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08009328 windowInSecondary->assertNoEvents();
9329
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009330 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009332 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009333 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08009334 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08009335 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08009336}
9337
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009338TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08009339 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08009340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009341 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009342 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009343 windowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08009344 windowInSecondary->assertNoEvents();
9345
9346 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009347 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009348 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08009349 windowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009350 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hungb92218b2018-08-14 12:00:21 +08009351
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009352 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009353 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08009354
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009355 // Old focus should receive a cancel event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009356 windowInSecondary->consumeKeyUp(ui::LogicalDisplayId::INVALID, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08009357
9358 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009359 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08009360 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009361 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08009362 windowInSecondary->assertNoEvents();
9363}
9364
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009365// Test per-display input monitors for motion event.
9366TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08009367 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009368 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08009369 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009370 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009371
9372 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009374 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9375 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009376 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009377 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9378 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009379 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009380 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009381
9382 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009383 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009384 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009385 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009386 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009387 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08009388 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08009389 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009390
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08009391 // Lift up the touch from the second display
9392 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009393 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08009394 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9395 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
9396 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
9397
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009398 // Test inject a non-pointer motion event.
9399 // If specific a display, it will dispatch to the focused window of particular display,
9400 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009401 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009402 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL,
9403 ui::LogicalDisplayId::INVALID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009404 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009405 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009406 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009407 windowInSecondary->consumeMotionDown(ui::LogicalDisplayId::INVALID);
9408 monitorInSecondary.consumeMotionDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009409}
9410
9411// Test per-display input monitors for key event.
9412TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009413 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08009414 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009415 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08009416 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009417 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009418
9419 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009420 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009421 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009422 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08009423 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009424 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
9425 monitorInSecondary.consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08009426}
9427
Vishnu Nair958da932020-08-21 17:12:37 -07009428TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
9429 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009430 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2",
9431 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009432 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009433 mDispatcher->onWindowInfosChanged(
9434 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
9435 *windowInSecondary->getInfo()},
9436 {},
9437 0,
9438 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009439 setFocusedWindow(secondWindowInPrimary);
9440 windowInPrimary->consumeFocusEvent(false);
9441 secondWindowInPrimary->consumeFocusEvent(true);
9442
9443 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009444 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009445 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009446 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07009447 windowInPrimary->assertNoEvents();
9448 windowInSecondary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009449 secondWindowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07009450}
9451
Arthur Hungdfd528e2021-12-08 13:23:04 +00009452TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
9453 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009454 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009455 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00009456 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009457
9458 // Test touch down on primary display.
9459 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009460 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9461 ui::LogicalDisplayId::DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009462 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009463 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9464 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009465
9466 // Test touch down on second display.
9467 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009468 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
9470 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
9471 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
9472
9473 // Trigger cancel touch.
9474 mDispatcher->cancelCurrentTouch();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009475 windowInPrimary->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
9476 monitorInPrimary.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00009477 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
9478 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
9479
9480 // Test inject a move motion event, no window/monitor should receive the event.
9481 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009482 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009483 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Arthur Hungdfd528e2021-12-08 13:23:04 +00009484 << "Inject motion event should return InputEventInjectionResult::FAILED";
9485 windowInPrimary->assertNoEvents();
9486 monitorInPrimary.assertNoEvents();
9487
9488 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009489 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00009490 SECOND_DISPLAY_ID, {110, 200}))
9491 << "Inject motion event should return InputEventInjectionResult::FAILED";
9492 windowInSecondary->assertNoEvents();
9493 monitorInSecondary.assertNoEvents();
9494}
9495
Hu Guocb134f12023-12-23 13:42:44 +00009496/**
9497 * Send a key to the primary display and to the secondary display.
9498 * Then cause the key on the primary display to be canceled by sending in a stale key.
9499 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
9500 * does not get canceled.
9501 */
9502TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
9503 // Send a key down on primary display
9504 mDispatcher->notifyKey(
9505 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009506 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009507 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9508 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009509 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
9510 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00009511 windowInSecondary->assertNoEvents();
9512
9513 // Send a key down on second display
9514 mDispatcher->notifyKey(
9515 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9516 .displayId(SECOND_DISPLAY_ID)
9517 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9518 .build());
9519 windowInSecondary->consumeKeyEvent(
9520 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
9521 windowInPrimary->assertNoEvents();
9522
9523 // Send a valid key up event on primary display that will be dropped because it is stale
9524 NotifyKeyArgs staleKeyUp =
9525 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009526 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009527 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9528 .build();
9529 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
9530 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
9531 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
9532 mDispatcher->notifyKey(staleKeyUp);
9533
9534 // Only the key gesture corresponding to the dropped event should receive the cancel event.
9535 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
9536 // receive any events.
9537 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009538 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
Hu Guocb134f12023-12-23 13:42:44 +00009539 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
9540 windowInSecondary->assertNoEvents();
9541}
9542
9543/**
9544 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
9545 */
9546TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
9547 // Send touch down on primary display.
9548 mDispatcher->notifyMotion(
9549 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9550 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009551 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009552 .build());
9553 windowInPrimary->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009554 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00009555 windowInSecondary->assertNoEvents();
9556
9557 // Send touch down on second display.
9558 mDispatcher->notifyMotion(
9559 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9560 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9561 .displayId(SECOND_DISPLAY_ID)
9562 .build());
9563 windowInPrimary->assertNoEvents();
9564 windowInSecondary->consumeMotionEvent(
9565 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
9566
9567 // inject a valid MotionEvent on primary display that will be stale when it arrives.
9568 NotifyMotionArgs staleMotionUp =
9569 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009570 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009571 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9572 .build();
9573 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
9574 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
9575 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
9576 mDispatcher->notifyMotion(staleMotionUp);
9577
9578 // For stale motion events, we let the gesture to complete. This behaviour is different from key
9579 // events, where we would cancel the current keys instead.
9580 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
9581 windowInSecondary->assertNoEvents();
9582}
9583
Jackal Guof9696682018-10-05 12:23:23 +08009584class InputFilterTest : public InputDispatcherTest {
9585protected:
Linnan Li13bf76a2024-05-05 19:18:02 +08009586 void testNotifyMotion(ui::LogicalDisplayId displayId, bool expectToBeFiltered,
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009587 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08009588 NotifyMotionArgs motionArgs;
9589
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009590 motionArgs =
9591 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009592 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009593 motionArgs =
9594 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009595 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009596 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08009597 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009598 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009599 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08009600 } else {
9601 mFakePolicy->assertFilterInputEventWasNotCalled();
9602 }
9603 }
9604
9605 void testNotifyKey(bool expectToBeFiltered) {
9606 NotifyKeyArgs keyArgs;
9607
9608 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009609 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009610 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009611 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009612 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08009613
9614 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08009615 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009616 } else {
9617 mFakePolicy->assertFilterInputEventWasNotCalled();
9618 }
9619 }
9620};
9621
9622// Test InputFilter for MotionEvent
9623TEST_F(InputFilterTest, MotionEvent_InputFilter) {
9624 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009625 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009626 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009627
9628 // Enable InputFilter
9629 mDispatcher->setInputFilterEnabled(true);
9630 // Test touch on both primary and second display, and check if both events are filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009631 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009632 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009633
9634 // Disable InputFilter
9635 mDispatcher->setInputFilterEnabled(false);
9636 // Test touch on both primary and second display, and check if both events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009637 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009638 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009639}
9640
9641// Test InputFilter for KeyEvent
9642TEST_F(InputFilterTest, KeyEvent_InputFilter) {
9643 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009644 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009645
9646 // Enable InputFilter
9647 mDispatcher->setInputFilterEnabled(true);
9648 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009649 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009650
9651 // Disable InputFilter
9652 mDispatcher->setInputFilterEnabled(false);
9653 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009654 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009655}
9656
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009657// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
9658// logical display coordinate space.
9659TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
9660 ui::Transform firstDisplayTransform;
9661 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
9662 ui::Transform secondDisplayTransform;
9663 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
9664
9665 std::vector<gui::DisplayInfo> displayInfos(2);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009666 displayInfos[0].displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009667 displayInfos[0].transform = firstDisplayTransform;
9668 displayInfos[1].displayId = SECOND_DISPLAY_ID;
9669 displayInfos[1].transform = secondDisplayTransform;
9670
Patrick Williamsd828f302023-04-28 17:52:08 -05009671 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009672
9673 // Enable InputFilter
9674 mDispatcher->setInputFilterEnabled(true);
9675
9676 // Ensure the correct transforms are used for the displays.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009677 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true,
9678 firstDisplayTransform);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009679 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009680}
9681
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009682class InputFilterInjectionPolicyTest : public InputDispatcherTest {
9683protected:
9684 virtual void SetUp() override {
9685 InputDispatcherTest::SetUp();
9686
9687 /**
9688 * We don't need to enable input filter to test the injected event policy, but we enabled it
9689 * here to make the tests more realistic, since this policy only matters when inputfilter is
9690 * on.
9691 */
9692 mDispatcher->setInputFilterEnabled(true);
9693
9694 std::shared_ptr<InputApplicationHandle> application =
9695 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009696 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009697 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009698
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009699 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009700 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009701 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009702 setFocusedWindow(mWindow);
9703 mWindow->consumeFocusEvent(true);
9704 }
9705
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009706 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9707 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009708 KeyEvent event;
9709
9710 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9711 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009712 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
9713 AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009714 const int32_t additionalPolicyFlags =
9715 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
9716 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009717 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009718 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009719 policyFlags | additionalPolicyFlags));
9720
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009721 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009722 }
9723
9724 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9725 int32_t flags) {
9726 MotionEvent event;
9727 PointerProperties pointerProperties[1];
9728 PointerCoords pointerCoords[1];
9729 pointerProperties[0].clear();
9730 pointerProperties[0].id = 0;
9731 pointerCoords[0].clear();
9732 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
9733 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
9734
9735 ui::Transform identityTransform;
9736 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9737 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
9738 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
9739 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
9740 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07009741 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07009742 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00009743 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009744
9745 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
9746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009747 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009748 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009749 policyFlags | additionalPolicyFlags));
9750
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009751 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009752 }
9753
9754private:
9755 sp<FakeWindowHandle> mWindow;
9756};
9757
9758TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009759 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
9760 // filter. Without it, the event will no different from a regularly injected event, and the
9761 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00009762 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
9763 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009764}
9765
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009766TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009767 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009768 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009769 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
9770}
9771
9772TEST_F(InputFilterInjectionPolicyTest,
9773 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
9774 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009775 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009776 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009777}
9778
9779TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00009780 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
9781 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009782}
9783
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009784class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
9785protected:
9786 virtual void SetUp() override {
9787 InputDispatcherTest::SetUp();
9788
9789 std::shared_ptr<FakeApplicationHandle> application =
9790 std::make_shared<FakeApplicationHandle>();
9791 application->setDispatchingTimeout(100ms);
9792 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009793 ui::LogicalDisplayId::DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00009794 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009795 mWindow->setDispatchingTimeout(100ms);
9796 mWindow->setFocusable(true);
9797
9798 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009799 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009800
9801 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
9802 setFocusedWindow(mWindow);
9803 mWindow->consumeFocusEvent(true);
9804 }
9805
Linnan Li13bf76a2024-05-05 19:18:02 +08009806 void notifyAndConsumeMotion(int32_t action, uint32_t source, ui::LogicalDisplayId displayId,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009807 nsecs_t eventTime) {
9808 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
9809 .displayId(displayId)
9810 .eventTime(eventTime)
9811 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9812 .build());
9813 mWindow->consumeMotionEvent(WithMotionAction(action));
9814 }
9815
9816private:
9817 sp<FakeWindowHandle> mWindow;
9818};
9819
9820TEST_F_WITH_FLAGS(
9821 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
9822 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9823 rate_limit_user_activity_poke_in_dispatcher))) {
9824 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
9825
9826 // First event of type TOUCH. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009827 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009828 milliseconds_to_nanoseconds(50));
9829 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009830 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
9831 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009832
9833 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009834 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009835 milliseconds_to_nanoseconds(130));
9836 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009837 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
9838 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009839
9840 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009841 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9842 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009843 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009844 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
9845 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009846
9847 // Within 50ns of previous TOUCH event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009848 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009849 milliseconds_to_nanoseconds(140));
9850 mFakePolicy->assertUserActivityNotPoked();
9851
9852 // Within 50ns of previous OTHER event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009853 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9854 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009855 mFakePolicy->assertUserActivityNotPoked();
9856
9857 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
9858 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009859 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009860 milliseconds_to_nanoseconds(160));
9861 mFakePolicy->assertUserActivityNotPoked();
9862
9863 // 65ns > 50ns has passed since previous OTHER event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009864 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9865 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009866 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009867 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
9868 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009869
9870 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009871 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009872 milliseconds_to_nanoseconds(300));
9873 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009874 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
9875 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009876
9877 // Assert that there's no more user activity poke event.
9878 mFakePolicy->assertUserActivityNotPoked();
9879}
9880
9881TEST_F_WITH_FLAGS(
9882 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
9883 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9884 rate_limit_user_activity_poke_in_dispatcher))) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009885 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009886 milliseconds_to_nanoseconds(200));
9887 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009888 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
9889 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009890
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009891 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009892 milliseconds_to_nanoseconds(280));
9893 mFakePolicy->assertUserActivityNotPoked();
9894
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009895 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009896 milliseconds_to_nanoseconds(340));
9897 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009898 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
9899 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009900}
9901
9902TEST_F_WITH_FLAGS(
9903 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
9904 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9905 rate_limit_user_activity_poke_in_dispatcher))) {
9906 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
9907
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009908 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9909 20);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009910 mFakePolicy->assertUserActivityPoked();
9911
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009912 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9913 30);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009914 mFakePolicy->assertUserActivityPoked();
9915}
9916
chaviwfd6d3512019-03-25 13:23:49 -07009917class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009918 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07009919 InputDispatcherTest::SetUp();
9920
Chris Yea209fde2020-07-22 13:54:51 -07009921 std::shared_ptr<FakeApplicationHandle> application =
9922 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009923 mUnfocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
9924 ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009925 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07009926
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009927 mFocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
9928 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009929 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07009930
9931 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009932 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07009933 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07009934
9935 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009936 mDispatcher->onWindowInfosChanged(
9937 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009938 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009939 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07009940 }
9941
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009942 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07009943 InputDispatcherTest::TearDown();
9944
9945 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009946 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07009947 }
9948
9949protected:
9950 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009951 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07009952 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07009953};
9954
9955// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9956// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
9957// the onPointerDownOutsideFocus callback.
9958TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009960 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9961 ui::LogicalDisplayId::DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009962 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009963 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009964
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009965 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07009966 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
9967}
9968
9969// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
9970// DOWN on the window that doesn't have focus. Ensure no window received the
9971// onPointerDownOutsideFocus callback.
9972TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009973 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009974 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009975 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009977 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009978
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009979 ASSERT_TRUE(mDispatcher->waitForIdle());
9980 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009981}
9982
9983// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
9984// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
9985TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08009986 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009987 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009988 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009989 mFocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009990
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009991 ASSERT_TRUE(mDispatcher->waitForIdle());
9992 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009993}
9994
9995// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9996// DOWN on the window that already has focus. Ensure no window received the
9997// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009998TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009999 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010000 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10001 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010002 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -070010003 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -070010004
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -080010005 ASSERT_TRUE(mDispatcher->waitForIdle());
10006 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -070010007}
10008
Prabir Pradhan47cf0a02021-03-11 20:30:57 -080010009// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
10010// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
10011TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
10012 const MotionEvent event =
10013 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
10014 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070010015 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -080010016 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
10017 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010018 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -080010019 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010020 mUnfocusedWindow->consumeAnyMotionDown(ui::LogicalDisplayId::DEFAULT,
10021 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Prabir Pradhan47cf0a02021-03-11 20:30:57 -080010022
10023 ASSERT_TRUE(mDispatcher->waitForIdle());
10024 mFakePolicy->assertOnPointerDownWasNotCalled();
10025 // Ensure that the unfocused window did not receive any FOCUS events.
10026 mUnfocusedWindow->assertNoEvents();
10027}
10028
chaviwaf87b3e2019-10-01 16:59:28 -070010029// These tests ensures we can send touch events to a single client when there are multiple input
10030// windows that point to the same client token.
10031class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
10032 virtual void SetUp() override {
10033 InputDispatcherTest::SetUp();
10034
Chris Yea209fde2020-07-22 13:54:51 -070010035 std::shared_ptr<FakeApplicationHandle> application =
10036 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010037 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010038 ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -070010039 mWindow1->setFrame(Rect(0, 0, 100, 100));
10040
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010041 mWindow2 = mWindow1->clone(ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -070010042 mWindow2->setFrame(Rect(100, 100, 200, 200));
10043
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010044 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -070010045 }
10046
10047protected:
10048 sp<FakeWindowHandle> mWindow1;
10049 sp<FakeWindowHandle> mWindow2;
10050
10051 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -050010052 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -070010053 vec2 vals = windowInfo->transform.transform(point.x, point.y);
10054 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -070010055 }
10056
10057 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
10058 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +010010059 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010060 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000010061 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010062 ASSERT_NE(nullptr, motionEvent);
10063 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -070010064
10065 for (size_t i = 0; i < points.size(); i++) {
10066 float expectedX = points[i].x;
10067 float expectedY = points[i].y;
10068
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010069 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -070010070 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010071 << ", got " << motionEvent->getX(i);
10072 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -070010073 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010074 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -070010075 }
10076 }
chaviw9eaa22c2020-07-01 16:21:27 -070010077
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010078 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
10079 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -070010080 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010081 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010082 ui::LogicalDisplayId::DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -070010083
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010084 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -070010085 }
chaviwaf87b3e2019-10-01 16:59:28 -070010086};
10087
10088TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
10089 // Touch Window 1
10090 PointF touchedPoint = {10, 10};
10091 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010092 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010093
10094 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010095 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010096
10097 // Touch Window 2
10098 touchedPoint = {150, 150};
10099 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010100 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010101}
10102
chaviw9eaa22c2020-07-01 16:21:27 -070010103TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
10104 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -070010105 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010106 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -070010107
10108 // Touch Window 1
10109 PointF touchedPoint = {10, 10};
10110 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010111 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010112 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010113 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010114
10115 // Touch Window 2
10116 touchedPoint = {150, 150};
10117 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010118 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
10119 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010120
chaviw9eaa22c2020-07-01 16:21:27 -070010121 // Update the transform so rotation is set
10122 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010123 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -070010124 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010125 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -070010126}
10127
chaviw9eaa22c2020-07-01 16:21:27 -070010128TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010129 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010130 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010131
10132 // Touch Window 1
10133 std::vector<PointF> touchedPoints = {PointF{10, 10}};
10134 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010135 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010136
10137 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010138 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
10139 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
10140 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -070010141 touchedPoints.push_back(PointF{150, 150});
10142 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010143 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010144
chaviw9eaa22c2020-07-01 16:21:27 -070010145 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010146 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -070010147 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010148
chaviw9eaa22c2020-07-01 16:21:27 -070010149 // Update the transform so rotation is set for Window 2
10150 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010151 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -070010152 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010153 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010154}
10155
chaviw9eaa22c2020-07-01 16:21:27 -070010156TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010157 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010158 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010159
10160 // Touch Window 1
10161 std::vector<PointF> touchedPoints = {PointF{10, 10}};
10162 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010163 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010164
10165 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -070010166 touchedPoints.push_back(PointF{150, 150});
10167 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010168
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010169 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010170
10171 // Move both windows
10172 touchedPoints = {{20, 20}, {175, 175}};
10173 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
10174 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
10175
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010176 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010177
chaviw9eaa22c2020-07-01 16:21:27 -070010178 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010179 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -070010180 expectedPoints.pop_back();
10181
10182 // Touch Window 2
10183 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010184 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -070010185 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010186 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -070010187
10188 // Move both windows
10189 touchedPoints = {{20, 20}, {175, 175}};
10190 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
10191 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
10192
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010193 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010194}
10195
10196TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
10197 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010198 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010199
10200 // Touch Window 1
10201 std::vector<PointF> touchedPoints = {PointF{10, 10}};
10202 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010203 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010204
10205 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -070010206 touchedPoints.push_back(PointF{150, 150});
10207 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010208
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010209 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010210
10211 // Move both windows
10212 touchedPoints = {{20, 20}, {175, 175}};
10213 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
10214 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
10215
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010216 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +000010217}
10218
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -070010219/**
10220 * When one of the windows is slippery, the touch should not slip into the other window with the
10221 * same input channel.
10222 */
10223TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
10224 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010225 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -070010226
10227 // Touch down in window 1
10228 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010229 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -070010230 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
10231
10232 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
10233 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
10234 // getting generated.
10235 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010236 ui::LogicalDisplayId::DEFAULT, {{150, 150}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -070010237
10238 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
10239}
10240
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010241/**
10242 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
10243 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
10244 * that the pointer is hovering over may have a different transform.
10245 */
10246TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010247 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010248
10249 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010250 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
10251 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10252 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010253 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
10254 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010255 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070010256 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10257 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
10258 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010259 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010260 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -070010261 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
10262}
10263
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010264class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
10265 virtual void SetUp() override {
10266 InputDispatcherTest::SetUp();
10267
Chris Yea209fde2020-07-22 13:54:51 -070010268 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010269 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010270 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010271 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010272 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010273 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -070010274 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010275
10276 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010277 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010278
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010279 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010280 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010281 mWindow->consumeFocusEvent(true);
10282 }
10283
10284 virtual void TearDown() override {
10285 InputDispatcherTest::TearDown();
10286 mWindow.clear();
10287 }
10288
10289protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010290 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -070010291 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010292 sp<FakeWindowHandle> mWindow;
10293 static constexpr PointF WINDOW_LOCATION = {20, 20};
10294
10295 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010296 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
10297 .x(WINDOW_LOCATION.x)
10298 .y(WINDOW_LOCATION.y);
10299 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10300 .pointer(touchingPointer)
10301 .build());
10302 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10303 .pointer(touchingPointer)
10304 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010305 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010306
10307 sp<FakeWindowHandle> addSpyWindow() {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010308 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy",
10309 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010310 spy->setTrustedOverlay(true);
10311 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010312 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010313 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010314 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010315 return spy;
10316 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010317};
10318
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010319// Send a tap and respond, which should not cause an ANR.
10320TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
10321 tapOnWindow();
10322 mWindow->consumeMotionDown();
10323 mWindow->consumeMotionUp();
10324 ASSERT_TRUE(mDispatcher->waitForIdle());
10325 mFakePolicy->assertNotifyAnrWasNotCalled();
10326}
10327
10328// Send a regular key and respond, which should not cause an ANR.
10329TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010330 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010331 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010332 ASSERT_TRUE(mDispatcher->waitForIdle());
10333 mFakePolicy->assertNotifyAnrWasNotCalled();
10334}
10335
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010336TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
10337 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010338 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010339 mWindow->consumeFocusEvent(false);
10340
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010341 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010342 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10343 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
10344 CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +000010345 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010347 // Key will not go to window because we have no focused window.
10348 // The 'no focused window' ANR timer should start instead.
10349
10350 // Now, the focused application goes away.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010351 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, nullptr);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -050010352 // The key should get dropped and there should be no ANR.
10353
10354 ASSERT_TRUE(mDispatcher->waitForIdle());
10355 mFakePolicy->assertNotifyAnrWasNotCalled();
10356}
10357
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010358// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010359// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10360// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010361TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010362 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010363 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10364 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010365
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010366 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010367 ASSERT_TRUE(sequenceNum);
10368 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010369 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010370
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010371 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010372 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010373 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010374 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010375 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010376}
10377
10378// Send a key to the app and have the app not respond right away.
10379TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
10380 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010381 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010382 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010383 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010384 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010385 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070010386 ASSERT_TRUE(mDispatcher->waitForIdle());
10387}
10388
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010389// We have a focused application, but no focused window
10390TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -070010391 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010392 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010393 mWindow->consumeFocusEvent(false);
10394
10395 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010396 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010397 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10398 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010399 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
10400 mDispatcher->waitForIdle();
10401 mFakePolicy->assertNotifyAnrWasNotCalled();
10402
10403 // Once a focused event arrives, we get an ANR for this application
10404 // We specify the injection timeout to be smaller than the application timeout, to ensure that
10405 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010406 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010407 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10408 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT, 50ms,
Linnan Li13bf76a2024-05-05 19:18:02 +080010409 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010410 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010411 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -070010412 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010413 ASSERT_TRUE(mDispatcher->waitForIdle());
10414}
10415
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010416/**
10417 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
10418 * there will not be an ANR.
10419 */
10420TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
10421 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010422 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010423 mWindow->consumeFocusEvent(false);
10424
10425 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -070010426 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
10427 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010428 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
10429 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
10430
10431 // Define a valid key down event that is stale (too old).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010432 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
10433 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN,
10434 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime,
10435 eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010436
Hu Guofe3c8f12023-09-22 17:20:15 +080010437 const int32_t policyFlags =
10438 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010439
10440 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +000010441 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -080010442 InputEventInjectionSync::WAIT_FOR_RESULT,
10443 INJECT_EVENT_TIMEOUT, policyFlags);
10444 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
10445 << "Injection should fail because the event is stale";
10446
10447 ASSERT_TRUE(mDispatcher->waitForIdle());
10448 mFakePolicy->assertNotifyAnrWasNotCalled();
10449 mWindow->assertNoEvents();
10450}
10451
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010452// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010453// Make sure that we don't notify policy twice about the same ANR.
10454TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010455 const std::chrono::duration appTimeout = 400ms;
10456 mApplication->setDispatchingTimeout(appTimeout);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010457 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010458
Vishnu Nair47074b82020-08-14 11:54:47 -070010459 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010460 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010461 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010462
10463 // Once a focused event arrives, we get an ANR for this application
10464 // We specify the injection timeout to be smaller than the application timeout, to ensure that
10465 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010466 const std::chrono::duration eventInjectionTimeout = 100ms;
10467 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010468 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010469 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10470 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT,
10471 eventInjectionTimeout,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -070010472 /*allowKeyRepeat=*/false);
10473 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
10474 << "result=" << ftl::enum_string(result);
10475 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
10476 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
10477 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
10478 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010479
Vishnu Naire4df8752022-09-08 09:17:55 -070010480 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010481 // ANR should not be raised again. It is up to policy to do that if it desires.
10482 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010483
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010484 // If we now get a focused window, the ANR should stop, but the policy handles that via
10485 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010486 ASSERT_TRUE(mDispatcher->waitForIdle());
10487}
10488
10489// We have a focused application, but no focused window
10490TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -070010491 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010492 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010493 mWindow->consumeFocusEvent(false);
10494
10495 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010496 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010497
Vishnu Naire4df8752022-09-08 09:17:55 -070010498 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10499 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010500
10501 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010502 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010503 ASSERT_TRUE(mDispatcher->waitForIdle());
10504 mWindow->assertNoEvents();
10505}
10506
10507/**
10508 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
10509 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
10510 * If we process 1 of the events, but ANR on the second event with the same timestamp,
10511 * the ANR mechanism should still work.
10512 *
10513 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
10514 * DOWN event, while not responding on the second one.
10515 */
10516TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
10517 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010518 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010519 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010520 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10521 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010522 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010523
10524 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010525 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010526 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010527 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
10528 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010529 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010530
10531 // 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 -070010532 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010533 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010534 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010535}
10536
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010537// A spy window can receive an ANR
10538TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
10539 sp<FakeWindowHandle> spy = addSpyWindow();
10540
10541 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010542 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10543 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010544 mWindow->consumeMotionDown();
10545
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010546 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010547 ASSERT_TRUE(sequenceNum);
10548 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010549 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010550
10551 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010552 spy->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010553 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010554 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010555 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010556}
10557
10558// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010559// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010560TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
10561 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010562
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010563 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010564 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
10565 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
10566 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10567 injectKeyUp(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010568
10569 // Stuck on the ACTION_UP
10570 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010571 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010572
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010573 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010574 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010575 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10576 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010577
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010578 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010579 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010580 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010581 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010582 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010583}
10584
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010585// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010586// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010587TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
10588 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010589
10590 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010591 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10592 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010593
10594 mWindow->consumeMotionDown();
10595 // Stuck on the ACTION_UP
10596 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010597 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010598
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010599 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010600 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010601 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10602 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010603
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010604 mWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010605 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010606 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010607 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010608 spy->assertNoEvents();
10609}
10610
10611TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010612 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010613
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010614 FakeMonitorReceiver monitor =
10615 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010616
10617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010618 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10619 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010620
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010621 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010622 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
10623 ASSERT_TRUE(consumeSeq);
10624
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010625 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
10626 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010627
10628 monitor.finishEvent(*consumeSeq);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010629 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010630
10631 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010632 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010633}
10634
10635// If a window is unresponsive, then you get anr. if the window later catches up and starts to
10636// process events, you don't get an anr. When the window later becomes unresponsive again, you
10637// get an ANR again.
10638// 1. tap -> block on ACTION_UP -> receive ANR
10639// 2. consume all pending events (= queue becomes healthy again)
10640// 3. tap again -> block on ACTION_UP again -> receive ANR second time
10641TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
10642 tapOnWindow();
10643
10644 mWindow->consumeMotionDown();
10645 // Block on ACTION_UP
10646 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010647 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010648 mWindow->consumeMotionUp(); // Now the connection should be healthy again
10649 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010650 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010651 mWindow->assertNoEvents();
10652
10653 tapOnWindow();
10654 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010655 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010656 mWindow->consumeMotionUp();
10657
10658 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010659 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010660 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010661 mWindow->assertNoEvents();
10662}
10663
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010664// If a connection remains unresponsive for a while, make sure policy is only notified once about
10665// it.
10666TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010668 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10669 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010670
10671 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010672 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010673 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010674 // 'notifyConnectionUnresponsive' should only be called once per connection
10675 mFakePolicy->assertNotifyAnrWasNotCalled();
10676 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010677 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010678 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010679 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010680 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010681 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010682 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010683 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010684}
10685
10686/**
10687 * 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 -070010688 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010689 */
10690TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010691 // The timeouts in this test are established by relying on the fact that the "key waiting for
10692 // events timeout" is equal to 500ms.
10693 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010694 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010695 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010696
10697 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010698 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010699 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010700 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010701 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010702
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010703 // Don't finish the events yet, and send a key
10704 mDispatcher->notifyKey(
10705 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10706 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10707 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010708 // Key will not be sent to the window, yet, because the window is still processing events
10709 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010710 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010711 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010712
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010713 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010714 // if we wait long enough though, dispatcher will give up, and still send the key
10715 // to the focused window, even though we have not yet finished the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010716 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010717 mWindow->finishEvent(*downSequenceNum);
10718 mWindow->finishEvent(*upSequenceNum);
10719}
10720
10721/**
10722 * If a window is processing a motion event, and then a key event comes in, the key event should
10723 * not go to the focused window until the motion is processed.
10724 * If then a new motion comes in, then the pending key event should be going to the currently
10725 * focused window right away.
10726 */
10727TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010728 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
10729 // The timeouts in this test are established by relying on the fact that the "key waiting for
10730 // events timeout" is equal to 500ms.
10731 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010732 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010733 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010734
10735 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010736 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010737 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010738 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010739 ASSERT_TRUE(upSequenceNum);
10740 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010741 mDispatcher->notifyKey(
10742 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10743 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10744 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010745 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010746 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010747
10748 // Now tap down again. It should cause the pending key to go to the focused window right away.
10749 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010750 // Now that we tapped, we should receive the key immediately.
10751 // Since there's still room for slowness, we use 200ms, which is much less than
10752 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
10753 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
10754 ASSERT_NE(nullptr, keyEvent);
10755 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
10756 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
10757 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
10758 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010759 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
10760 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010761 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10762 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010763 mWindow->assertNoEvents();
10764}
10765
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010766/**
10767 * Send an event to the app and have the app not respond right away.
10768 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10769 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
10770 * At some point, the window becomes responsive again.
10771 * Ensure that subsequent events get dropped, and the next gesture is delivered.
10772 */
10773TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
10774 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10775 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
10776 .build());
10777
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010778 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010779 ASSERT_TRUE(sequenceNum);
10780 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10781 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10782
10783 mWindow->finishEvent(*sequenceNum);
10784 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
10785 ASSERT_TRUE(mDispatcher->waitForIdle());
10786 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10787
10788 // Now that the window is responsive, let's continue the gesture.
10789 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10790 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10791 .build());
10792
10793 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10794 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10795 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10796 .build());
10797
10798 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10799 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10800 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10801 .build());
10802 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10803 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10804 .build());
10805 // We already canceled this pointer, so the window shouldn't get any new events.
10806 mWindow->assertNoEvents();
10807
10808 // Start another one.
10809 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10810 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
10811 .build());
10812 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10813}
10814
Prabir Pradhanfc364722024-02-08 17:51:20 +000010815// Send an event to the app and have the app not respond right away. Then remove the app window.
10816// When the window is removed, the dispatcher will cancel the events for that window.
10817// So InputDispatcher will enqueue ACTION_CANCEL event as well.
10818TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
10819 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010820 AINPUT_SOURCE_TOUCHSCREEN,
10821 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010822
10823 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10824 ASSERT_TRUE(sequenceNum);
10825
10826 // Remove the window, but the input channel should remain alive.
10827 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10828
10829 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10830 // Since the window was removed, Dispatcher does not know the PID associated with the window
10831 // anymore, so the policy is notified without the PID.
10832 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
10833 /*pid=*/std::nullopt);
10834
10835 mWindow->finishEvent(*sequenceNum);
10836 // The cancellation was generated when the window was removed, along with the focus event.
10837 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010838 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010839 mWindow->consumeFocusEvent(false);
10840 ASSERT_TRUE(mDispatcher->waitForIdle());
10841 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10842}
10843
10844// Send an event to the app and have the app not respond right away. Wait for the policy to be
10845// notified of the unresponsive window, then remove the app window.
10846TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
10847 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010848 AINPUT_SOURCE_TOUCHSCREEN,
10849 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010850
10851 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10852 ASSERT_TRUE(sequenceNum);
10853 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10854 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10855
10856 // Remove the window, but the input channel should remain alive.
10857 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10858
10859 mWindow->finishEvent(*sequenceNum);
10860 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
10861 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010862 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010863 mWindow->consumeFocusEvent(false);
10864 ASSERT_TRUE(mDispatcher->waitForIdle());
10865 // Since the window was removed, Dispatcher does not know the PID associated with the window
10866 // becoming responsive, so the policy is notified without the PID.
10867 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10868}
10869
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010870class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
10871 virtual void SetUp() override {
10872 InputDispatcherTest::SetUp();
10873
Chris Yea209fde2020-07-22 13:54:51 -070010874 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010875 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010876 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010877 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010878 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010879 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010880 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010881
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010882 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010883 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010884 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010885 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010886
10887 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010888 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -070010889 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010890
10891 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010892 mDispatcher->onWindowInfosChanged(
10893 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010894 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010895 mFocusedWindow->consumeFocusEvent(true);
10896 }
10897
10898 virtual void TearDown() override {
10899 InputDispatcherTest::TearDown();
10900
10901 mUnfocusedWindow.clear();
10902 mFocusedWindow.clear();
10903 }
10904
10905protected:
Chris Yea209fde2020-07-22 13:54:51 -070010906 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010907 sp<FakeWindowHandle> mUnfocusedWindow;
10908 sp<FakeWindowHandle> mFocusedWindow;
10909 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
10910 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
10911 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
10912
10913 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
10914
10915 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
10916
10917private:
10918 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010919 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010920 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10921 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010923 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10924 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010925 }
10926};
10927
10928// If we have 2 windows that are both unresponsive, the one with the shortest timeout
10929// should be ANR'd first.
10930TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010931 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010932 injectMotionEvent(*mDispatcher,
10933 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10934 AINPUT_SOURCE_TOUCHSCREEN)
10935 .pointer(PointerBuilder(0, ToolType::FINGER)
10936 .x(FOCUSED_WINDOW_LOCATION.x)
10937 .y(FOCUSED_WINDOW_LOCATION.y))
10938 .build()));
10939 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10940 injectMotionEvent(*mDispatcher,
10941 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
10942 AINPUT_SOURCE_TOUCHSCREEN)
10943 .pointer(PointerBuilder(0, ToolType::FINGER)
10944 .x(FOCUSED_WINDOW_LOCATION.x)
10945 .y(FOCUSED_WINDOW_LOCATION.y))
10946 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010947 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010948 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010949 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010950 // We consumed all events, so no ANR
10951 ASSERT_TRUE(mDispatcher->waitForIdle());
10952 mFakePolicy->assertNotifyAnrWasNotCalled();
10953
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010954 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010955 injectMotionEvent(*mDispatcher,
10956 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10957 AINPUT_SOURCE_TOUCHSCREEN)
10958 .pointer(PointerBuilder(0, ToolType::FINGER)
10959 .x(FOCUSED_WINDOW_LOCATION.x)
10960 .y(FOCUSED_WINDOW_LOCATION.y))
10961 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010962 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010963 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010964
10965 const std::chrono::duration timeout =
10966 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010967 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010968
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010969 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010970 mFocusedWindow->consumeMotionDown();
10971 // This cancel is generated because the connection was unresponsive
10972 mFocusedWindow->consumeMotionCancel();
10973 mFocusedWindow->assertNoEvents();
10974 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010975 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010976 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10977 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010978 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010979}
10980
10981// If we have 2 windows with identical timeouts that are both unresponsive,
10982// it doesn't matter which order they should have ANR.
10983// But we should receive ANR for both.
10984TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
10985 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010986 mUnfocusedWindow->setDispatchingTimeout(
10987 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010988 mDispatcher->onWindowInfosChanged(
10989 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010990
10991 tapOnFocusedWindow();
10992 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010993 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010994 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
10995 mFocusedWindow->getDispatchingTimeout(
10996 DISPATCHING_TIMEOUT)),
10997 mFakePolicy->getUnresponsiveWindowToken(0ms)};
10998
10999 ASSERT_THAT(anrConnectionTokens,
11000 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
11001 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011002
11003 ASSERT_TRUE(mDispatcher->waitForIdle());
11004 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011005
11006 mFocusedWindow->consumeMotionDown();
11007 mFocusedWindow->consumeMotionUp();
11008 mUnfocusedWindow->consumeMotionOutside();
11009
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070011010 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
11011 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011012
11013 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070011014 ASSERT_THAT(responsiveTokens,
11015 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
11016 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011017 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011018}
11019
11020// If a window is already not responding, the second tap on the same window should be ignored.
11021// We should also log an error to account for the dropped event (not tested here).
11022// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
11023TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
11024 tapOnFocusedWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011025 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011026 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011027 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011028 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011029 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011030 ASSERT_TRUE(upEventSequenceNum);
11031 const std::chrono::duration timeout =
11032 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080011033 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011034
11035 // Tap once again
11036 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011037 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011038 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11039 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011040 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011041 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011042 FOCUSED_WINDOW_LOCATION));
11043 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
11044 // valid touch target
11045 mUnfocusedWindow->assertNoEvents();
11046
11047 // Consume the first tap
11048 mFocusedWindow->finishEvent(*downEventSequenceNum);
11049 mFocusedWindow->finishEvent(*upEventSequenceNum);
11050 ASSERT_TRUE(mDispatcher->waitForIdle());
11051 // The second tap did not go to the focused window
11052 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011053 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -080011054 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
11055 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011056 mFakePolicy->assertNotifyAnrWasNotCalled();
11057}
11058
11059// If you tap outside of all windows, there will not be ANR
11060TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011061 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011062 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11063 ui::LogicalDisplayId::DEFAULT, LOCATION_OUTSIDE_ALL_WINDOWS));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011064 ASSERT_TRUE(mDispatcher->waitForIdle());
11065 mFakePolicy->assertNotifyAnrWasNotCalled();
11066}
11067
11068// Since the focused window is paused, tapping on it should not produce any events
11069TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
11070 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011071 mDispatcher->onWindowInfosChanged(
11072 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011073
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011074 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011075 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11076 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011077
11078 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
11079 ASSERT_TRUE(mDispatcher->waitForIdle());
11080 // Should not ANR because the window is paused, and touches shouldn't go to it
11081 mFakePolicy->assertNotifyAnrWasNotCalled();
11082
11083 mFocusedWindow->assertNoEvents();
11084 mUnfocusedWindow->assertNoEvents();
11085}
11086
11087/**
11088 * 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 -070011089 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011090 * If a different window becomes focused at this time, the key should go to that window instead.
11091 *
11092 * Warning!!!
11093 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
11094 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011095 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011096 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
11097 *
11098 * If that value changes, this test should also change.
11099 */
11100TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
11101 // Set a long ANR timeout to prevent it from triggering
11102 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011103 mDispatcher->onWindowInfosChanged(
11104 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011105
11106 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011107 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011108 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011109 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011110 ASSERT_TRUE(upSequenceNum);
11111 // Don't finish the events yet, and send a key
11112 // Injection will succeed because we will eventually give up and send the key to the focused
11113 // window even if motions are still being processed.
11114
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011115 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011116 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
11117 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080011118 /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011119 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011120 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011121 // and the key remains pending, waiting for the touch events to be processed.
11122 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
11123 // under the hood.
11124 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
11125 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011126
11127 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -070011128 mFocusedWindow->setFocusable(false);
11129 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011130 mDispatcher->onWindowInfosChanged(
11131 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011132 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011133
11134 // Focus events should precede the key events
11135 mUnfocusedWindow->consumeFocusEvent(true);
11136 mFocusedWindow->consumeFocusEvent(false);
11137
11138 // Finish the tap events, which should unblock dispatcher
11139 mUnfocusedWindow->finishEvent(*downSequenceNum);
11140 mUnfocusedWindow->finishEvent(*upSequenceNum);
11141
11142 // Now that all queues are cleared and no backlog in the connections, the key event
11143 // can finally go to the newly focused "mUnfocusedWindow".
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011144 mUnfocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011145 mFocusedWindow->assertNoEvents();
11146 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011147 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011148}
11149
11150// When the touch stream is split across 2 windows, and one of them does not respond,
11151// then ANR should be raised and the touch should be canceled for the unresponsive window.
11152// The other window should not be affected by that.
11153TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
11154 // Touch Window 1
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011155 mDispatcher->notifyMotion(
11156 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
11157 ui::LogicalDisplayId::DEFAULT, {FOCUSED_WINDOW_LOCATION}));
11158 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011159
11160 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +000011161 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011162 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
11163 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +000011164 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011165
11166 const std::chrono::duration timeout =
11167 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080011168 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011169
11170 mUnfocusedWindow->consumeMotionDown();
11171 mFocusedWindow->consumeMotionDown();
11172 // Focused window may or may not receive ACTION_MOVE
11173 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080011174 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011175 ASSERT_TRUE(moveOrCancelSequenceNum);
11176 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
11177 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -070011178 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011179 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
11180 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
11181 mFocusedWindow->consumeMotionCancel();
11182 } else {
11183 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
11184 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011185 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080011186 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
11187 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011188
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011189 mUnfocusedWindow->assertNoEvents();
11190 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050011191 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070011192}
11193
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011194/**
11195 * If we have no focused window, and a key comes in, we start the ANR timer.
11196 * The focused application should add a focused window before the timer runs out to prevent ANR.
11197 *
11198 * If the user touches another application during this time, the key should be dropped.
11199 * Next, if a new focused window comes in, without toggling the focused application,
11200 * then no ANR should occur.
11201 *
11202 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
11203 * but in some cases the policy may not update the focused application.
11204 */
11205TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
11206 std::shared_ptr<FakeApplicationHandle> focusedApplication =
11207 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -070011208 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011209 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, focusedApplication);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011210 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
11211 mFocusedWindow->setFocusable(false);
11212
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011213 mDispatcher->onWindowInfosChanged(
11214 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011215 mFocusedWindow->consumeFocusEvent(false);
11216
11217 // Send a key. The ANR timer should start because there is no focused window.
11218 // 'focusedApplication' will get blamed if this timer completes.
11219 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011220 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011221 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
11222 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080011223 /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +000011224 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011226
11227 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
11228 // then the injected touches won't cause the focused event to get dropped.
11229 // The dispatcher only checks for whether the queue should be pruned upon queueing.
11230 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
11231 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
11232 // For this test, it means that the key would get delivered to the window once it becomes
11233 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011234 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011235
11236 // Touch unfocused window. This should force the pending key to get dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011237 mDispatcher->notifyMotion(
11238 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
11239 ui::LogicalDisplayId::DEFAULT, {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011240
11241 // We do not consume the motion right away, because that would require dispatcher to first
11242 // process (== drop) the key event, and by that time, ANR will be raised.
11243 // Set the focused window first.
11244 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011245 mDispatcher->onWindowInfosChanged(
11246 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050011247 setFocusedWindow(mFocusedWindow);
11248 mFocusedWindow->consumeFocusEvent(true);
11249 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
11250 // to another application. This could be a bug / behaviour in the policy.
11251
11252 mUnfocusedWindow->consumeMotionDown();
11253
11254 ASSERT_TRUE(mDispatcher->waitForIdle());
11255 // Should not ANR because we actually have a focused window. It was just added too slowly.
11256 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
11257}
11258
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011259/**
11260 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
11261 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
11262 * dispatcher doesn't prune pointer events incorrectly.
11263 *
11264 * This test reproduces a crash in InputDispatcher.
11265 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
11266 *
11267 * Keep the currently focused application (mApplication), and have no focused window.
11268 * We set up two additional windows:
11269 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
11270 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
11271 * window. This window is not focusable, but is touchable.
11272 *
11273 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
11274 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
11275 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
11276 *
11277 * Now, we touch "Another window". This window is owned by a different application than
11278 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
11279 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
11280 * dropping the events from its queue. Ensure that no crash occurs.
11281 *
11282 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
11283 * This does not affect the test running time.
11284 */
11285TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
11286 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
11287 std::make_shared<FakeApplicationHandle>();
11288 systemUiApplication->setDispatchingTimeout(3000ms);
11289 mFakePolicy->setStaleEventTimeout(3000ms);
11290 sp<FakeWindowHandle> navigationBar =
11291 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011292 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011293 navigationBar->setFocusable(false);
11294 navigationBar->setWatchOutsideTouch(true);
11295 navigationBar->setFrame(Rect(0, 0, 100, 100));
11296
11297 mApplication->setDispatchingTimeout(3000ms);
11298 // 'mApplication' is already focused, but we call it again here to make it explicit.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011299 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011300
11301 std::shared_ptr<FakeApplicationHandle> anotherApplication =
11302 std::make_shared<FakeApplicationHandle>();
11303 sp<FakeWindowHandle> appWindow =
11304 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011305 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011306 appWindow->setFocusable(false);
11307 appWindow->setFrame(Rect(100, 100, 200, 200));
11308
11309 mDispatcher->onWindowInfosChanged(
11310 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
11311 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
11312 mFocusedWindow->consumeFocusEvent(false);
11313
11314 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
11315 // in response.
11316 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11317 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
11318 .build());
11319 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
11320
11321 // Key will not be sent anywhere because we have no focused window. It will remain pending.
11322 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
11323 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011324 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
11325 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080011326 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011327 /*allowKeyRepeat=*/false);
11328 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
11329
11330 // Finish the gesture - lift up finger and inject ACTION_UP key event
11331 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
11332 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
11333 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011334 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0,
11335 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080011336 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080011337 /*allowKeyRepeat=*/false);
11338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
11339 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
11340 // getting any events yet.
11341 navigationBar->assertNoEvents();
11342
11343 // Now touch "Another window". This touch is going to a different application than the one we
11344 // are waiting for (which is 'mApplication').
11345 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
11346 // trying to be injected) and to continue processing the rest of the events in the original
11347 // order.
11348 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11349 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
11350 .build());
11351 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
11352 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
11353 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
11354
11355 appWindow->assertNoEvents();
11356 navigationBar->assertNoEvents();
11357}
11358
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011359// These tests ensure we cannot send touch events to a window that's positioned behind a window
11360// that has feature NO_INPUT_CHANNEL.
11361// Layout:
11362// Top (closest to user)
11363// mNoInputWindow (above all windows)
11364// mBottomWindow
11365// Bottom (furthest from user)
11366class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
11367 virtual void SetUp() override {
11368 InputDispatcherTest::SetUp();
11369
11370 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011371 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
11372 "Window without input channel",
11373 ui::LogicalDisplayId::DEFAULT,
11374 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011375 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011376 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
11377 // It's perfectly valid for this window to not have an associated input channel
11378
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011379 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011380 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011381 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
11382
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011383 mDispatcher->onWindowInfosChanged(
11384 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011385 }
11386
11387protected:
11388 std::shared_ptr<FakeApplicationHandle> mApplication;
11389 sp<FakeWindowHandle> mNoInputWindow;
11390 sp<FakeWindowHandle> mBottomWindow;
11391};
11392
11393TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
11394 PointF touchedPoint = {10, 10};
11395
Prabir Pradhan678438e2023-04-13 19:32:51 +000011396 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011397 AINPUT_SOURCE_TOUCHSCREEN,
11398 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011399
11400 mNoInputWindow->assertNoEvents();
11401 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
11402 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
11403 // and therefore should prevent mBottomWindow from receiving touches
11404 mBottomWindow->assertNoEvents();
11405}
11406
11407/**
11408 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
11409 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
11410 */
11411TEST_F(InputDispatcherMultiWindowOcclusionTests,
11412 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011413 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
11414 "Window with input channel and NO_INPUT_CHANNEL",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011415 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011416
Prabir Pradhan51e7db02022-02-07 06:02:57 -080011417 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011418 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011419 mDispatcher->onWindowInfosChanged(
11420 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011421
11422 PointF touchedPoint = {10, 10};
11423
Prabir Pradhan678438e2023-04-13 19:32:51 +000011424 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011425 AINPUT_SOURCE_TOUCHSCREEN,
11426 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050011427
11428 mNoInputWindow->assertNoEvents();
11429 mBottomWindow->assertNoEvents();
11430}
11431
Vishnu Nair958da932020-08-21 17:12:37 -070011432class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
11433protected:
11434 std::shared_ptr<FakeApplicationHandle> mApp;
11435 sp<FakeWindowHandle> mWindow;
11436 sp<FakeWindowHandle> mMirror;
11437
11438 virtual void SetUp() override {
11439 InputDispatcherTest::SetUp();
11440 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011441 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11442 ui::LogicalDisplayId::DEFAULT);
11443 mMirror = mWindow->clone(ui::LogicalDisplayId::DEFAULT);
11444 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Vishnu Nair958da932020-08-21 17:12:37 -070011445 mWindow->setFocusable(true);
11446 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011447 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011448 }
11449};
11450
11451TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
11452 // Request focus on a mirrored window
11453 setFocusedWindow(mMirror);
11454
11455 // window gets focused
11456 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011458 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011459 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011460}
11461
11462// A focused & mirrored window remains focused only if the window and its mirror are both
11463// focusable.
11464TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
11465 setFocusedWindow(mMirror);
11466
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000011467 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -070011468 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011470 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011471 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011472 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011473 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011474 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011475
11476 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011477 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011478
11479 // window loses focus since one of the windows associated with the token in not focusable
11480 mWindow->consumeFocusEvent(false);
11481
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011482 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011483 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011484 mWindow->assertNoEvents();
11485}
11486
11487// A focused & mirrored window remains focused until the window and its mirror both become
11488// invisible.
11489TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
11490 setFocusedWindow(mMirror);
11491
11492 // window gets focused
11493 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011495 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011496 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011497 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011498 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011499 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011500
11501 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011502 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011503
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011504 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011505 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011506 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011507 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011508 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011509 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011510
11511 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011512 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011513
11514 // window loses focus only after all windows associated with the token become invisible.
11515 mWindow->consumeFocusEvent(false);
11516
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011517 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011518 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011519 mWindow->assertNoEvents();
11520}
11521
11522// A focused & mirrored window remains focused until both windows are removed.
11523TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
11524 setFocusedWindow(mMirror);
11525
11526 // window gets focused
11527 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011528 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011529 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011530 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011531 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011532 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011533 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011534
11535 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011536 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011537
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011538 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011539 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011540 mMirror->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011541 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011542 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011543 mMirror->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070011544
11545 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011546 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011547 mWindow->consumeFocusEvent(false);
11548
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011549 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011550 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011551 mWindow->assertNoEvents();
11552}
11553
11554// Focus request can be pending until one window becomes visible.
11555TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
11556 // Request focus on an invisible mirror.
11557 mWindow->setVisible(false);
11558 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011559 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011560 setFocusedWindow(mMirror);
11561
11562 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011563 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011564 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011565 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -070011566
11567 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011568 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011569
11570 // window gets focused
11571 mWindow->consumeFocusEvent(true);
11572 // window gets the pending key event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011573 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -070011574}
Prabir Pradhan99987712020-11-10 18:43:05 -080011575
11576class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
11577protected:
11578 std::shared_ptr<FakeApplicationHandle> mApp;
11579 sp<FakeWindowHandle> mWindow;
11580 sp<FakeWindowHandle> mSecondWindow;
11581
11582 void SetUp() override {
11583 InputDispatcherTest::SetUp();
11584 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011585 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11586 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080011587 mWindow->setFocusable(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011588 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11589 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080011590 mSecondWindow->setFocusable(true);
11591
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011592 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011593 mDispatcher->onWindowInfosChanged(
11594 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -080011595
11596 setFocusedWindow(mWindow);
11597 mWindow->consumeFocusEvent(true);
11598 }
11599
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011600 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011601 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -080011602 }
11603
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011604 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
11605 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -080011606 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +090011607 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011608 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011609 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011610 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -080011611 }
11612};
11613
11614TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
11615 // Ensure that capture cannot be obtained for unfocused windows.
11616 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11617 mFakePolicy->assertSetPointerCaptureNotCalled();
11618 mSecondWindow->assertNoEvents();
11619
11620 // Ensure that capture can be enabled from the focus window.
11621 requestAndVerifyPointerCapture(mWindow, true);
11622
11623 // Ensure that capture cannot be disabled from a window that does not have capture.
11624 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
11625 mFakePolicy->assertSetPointerCaptureNotCalled();
11626
11627 // Ensure that capture can be disabled from the window with capture.
11628 requestAndVerifyPointerCapture(mWindow, false);
11629}
11630
11631TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011632 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011633
11634 setFocusedWindow(mSecondWindow);
11635
11636 // Ensure that the capture disabled event was sent first.
11637 mWindow->consumeCaptureEvent(false);
11638 mWindow->consumeFocusEvent(false);
11639 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +090011640 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011641
11642 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011643 notifyPointerCaptureChanged({});
11644 notifyPointerCaptureChanged(request);
11645 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -080011646 mWindow->assertNoEvents();
11647 mSecondWindow->assertNoEvents();
11648 mFakePolicy->assertSetPointerCaptureNotCalled();
11649}
11650
11651TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011652 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011653
11654 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011655 notifyPointerCaptureChanged({});
11656 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011657
11658 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +090011659 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011660 mWindow->consumeCaptureEvent(false);
11661 mWindow->assertNoEvents();
11662}
11663
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011664TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
11665 requestAndVerifyPointerCapture(mWindow, true);
11666
11667 // The first window loses focus.
11668 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +090011669 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011670 mWindow->consumeCaptureEvent(false);
11671
11672 // Request Pointer Capture from the second window before the notification from InputReader
11673 // arrives.
11674 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011675 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011676
11677 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011678 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011679
11680 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011681 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011682
11683 mSecondWindow->consumeFocusEvent(true);
11684 mSecondWindow->consumeCaptureEvent(true);
11685}
11686
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011687TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
11688 // App repeatedly enables and disables capture.
11689 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011690 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011691 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011692 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011693 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011694 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011695
11696 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
11697 // first request is now stale, this should do nothing.
11698 notifyPointerCaptureChanged(firstRequest);
11699 mWindow->assertNoEvents();
11700
11701 // InputReader notifies that the second request was enabled.
11702 notifyPointerCaptureChanged(secondRequest);
11703 mWindow->consumeCaptureEvent(true);
11704}
11705
Prabir Pradhan7092e262022-05-03 16:51:09 +000011706TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
11707 requestAndVerifyPointerCapture(mWindow, true);
11708
11709 // App toggles pointer capture off and on.
11710 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011711 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011712
11713 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011714 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011715
11716 // InputReader notifies that the latest "enable" request was processed, while skipping over the
11717 // preceding "disable" request.
11718 notifyPointerCaptureChanged(enableRequest);
11719
11720 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
11721 // any notifications.
11722 mWindow->assertNoEvents();
11723}
11724
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011725/**
11726 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
11727 * mouse movements don't affect the previous mouse hovering state.
11728 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
11729 * HOVER_MOVE events).
11730 */
11731TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
11732 // Mouse hover on the window
11733 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11734 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11735 .build());
11736 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11737 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11738 .build());
11739
11740 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
11741 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
11742
11743 // Start pointer capture
11744 requestAndVerifyPointerCapture(mWindow, true);
11745
11746 // Send some relative mouse movements and receive them in the window.
11747 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
11748 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
11749 .build());
11750 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
11751 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
11752
11753 // Stop pointer capture
11754 requestAndVerifyPointerCapture(mWindow, false);
11755
11756 // Continue hovering on the window
11757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11758 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
11759 .build());
11760 mWindow->consumeMotionEvent(
11761 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
11762
11763 mWindow->assertNoEvents();
11764}
11765
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011766TEST_F(InputDispatcherPointerCaptureTests, MultiDisplayPointerCapture) {
11767 // The default display is the focused display to begin with.
11768 requestAndVerifyPointerCapture(mWindow, true);
11769
11770 // Move the second window to a second display, make it the focused window on that display.
11771 mSecondWindow->editInfo()->displayId = SECOND_DISPLAY_ID;
11772 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11773 setFocusedWindow(mSecondWindow);
11774 mSecondWindow->consumeFocusEvent(true);
11775
11776 mWindow->assertNoEvents();
11777
11778 // The second window cannot gain capture because it is not on the focused display.
11779 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11780 mFakePolicy->assertSetPointerCaptureNotCalled();
11781 mSecondWindow->assertNoEvents();
11782
11783 // Make the second display the focused display.
11784 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +000011785 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011786
11787 // This causes the first window to lose pointer capture, and it's unable to request capture.
11788 mWindow->consumeCaptureEvent(false);
11789 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11790
11791 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11792 mFakePolicy->assertSetPointerCaptureNotCalled();
11793
11794 // The second window is now able to gain pointer capture successfully.
11795 requestAndVerifyPointerCapture(mSecondWindow, true);
11796}
11797
Hiroki Sato25040232024-02-22 17:21:22 +090011798using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
11799
11800TEST_F(InputDispatcherPointerCaptureDeathTest,
11801 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
11802 testing::GTEST_FLAG(death_test_style) = "threadsafe";
11803 ScopedSilentDeath _silentDeath;
11804
11805 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11806 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11807
11808 // Dispatch a pointer changed event with a wrong token.
11809 request.window = mSecondWindow->getToken();
11810 ASSERT_DEATH(
11811 {
11812 notifyPointerCaptureChanged(request);
11813 mSecondWindow->consumeCaptureEvent(true);
11814 },
11815 "Unexpected requested window for Pointer Capture.");
11816}
11817
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011818class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
11819protected:
11820 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000011821
11822 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
11823 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
11824
11825 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
11826 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11827
11828 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
11829 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
11830 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11831 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
11832 MAXIMUM_OBSCURING_OPACITY);
11833
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011834 static constexpr gui::Uid TOUCHED_APP_UID{10001};
11835 static constexpr gui::Uid APP_B_UID{10002};
11836 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011837
11838 sp<FakeWindowHandle> mTouchWindow;
11839
11840 virtual void SetUp() override {
11841 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011842 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011843 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
11844 }
11845
11846 virtual void TearDown() override {
11847 InputDispatcherTest::TearDown();
11848 mTouchWindow.clear();
11849 }
11850
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011851 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050011852 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011853 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011854 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011855 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011856 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011857 return window;
11858 }
11859
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011860 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011861 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
11862 sp<FakeWindowHandle> window =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011863 sp<FakeWindowHandle>::make(app, mDispatcher, name, ui::LogicalDisplayId::DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011864 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011865 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011866 return window;
11867 }
11868
11869 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011870 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011871 AINPUT_SOURCE_TOUCHSCREEN,
11872 ui::LogicalDisplayId::DEFAULT, points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011873 }
11874};
11875
11876TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011877 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011878 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011879 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011880
11881 touch();
11882
11883 mTouchWindow->assertNoEvents();
11884}
11885
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011886TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000011887 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
11888 const sp<FakeWindowHandle>& w =
11889 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011890 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011891
11892 touch();
11893
11894 mTouchWindow->assertNoEvents();
11895}
11896
11897TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011898 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
11899 const sp<FakeWindowHandle>& w =
11900 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011901 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011902
11903 touch();
11904
11905 w->assertNoEvents();
11906}
11907
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011908TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011909 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011910 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011911
11912 touch();
11913
11914 mTouchWindow->consumeAnyMotionDown();
11915}
11916
11917TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011918 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011919 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011920 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011921 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011922
11923 touch({PointF{100, 100}});
11924
11925 mTouchWindow->consumeAnyMotionDown();
11926}
11927
11928TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011929 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011930 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011931 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011932
11933 touch();
11934
11935 mTouchWindow->consumeAnyMotionDown();
11936}
11937
11938TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
11939 const sp<FakeWindowHandle>& w =
11940 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011941 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011942
11943 touch();
11944
11945 mTouchWindow->consumeAnyMotionDown();
11946}
11947
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011948TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
11949 const sp<FakeWindowHandle>& w =
11950 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011951 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011952
11953 touch();
11954
11955 w->assertNoEvents();
11956}
11957
11958/**
11959 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
11960 * inside) while letting them pass-through. Note that even though touch passes through the occluding
11961 * window, the occluding window will still receive ACTION_OUTSIDE event.
11962 */
11963TEST_F(InputDispatcherUntrustedTouchesTest,
11964 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
11965 const sp<FakeWindowHandle>& w =
11966 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011967 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011968 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011969
11970 touch();
11971
11972 w->consumeMotionOutside();
11973}
11974
11975TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
11976 const sp<FakeWindowHandle>& w =
11977 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011978 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011979 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011980
11981 touch();
11982
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011983 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011984}
11985
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011986TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011987 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011988 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11989 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011990 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011991
11992 touch();
11993
11994 mTouchWindow->consumeAnyMotionDown();
11995}
11996
11997TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
11998 const sp<FakeWindowHandle>& w =
11999 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12000 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012001 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012002
12003 touch();
12004
12005 mTouchWindow->consumeAnyMotionDown();
12006}
12007
12008TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012009 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012010 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12011 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012012 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012013
12014 touch();
12015
12016 mTouchWindow->assertNoEvents();
12017}
12018
12019TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
12020 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
12021 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012022 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
12023 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012024 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012025 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
12026 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012027 mDispatcher->onWindowInfosChanged(
12028 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012029
12030 touch();
12031
12032 mTouchWindow->assertNoEvents();
12033}
12034
12035TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
12036 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
12037 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012038 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
12039 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012040 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012041 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
12042 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012043 mDispatcher->onWindowInfosChanged(
12044 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012045
12046 touch();
12047
12048 mTouchWindow->consumeAnyMotionDown();
12049}
12050
12051TEST_F(InputDispatcherUntrustedTouchesTest,
12052 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
12053 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012054 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12055 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012056 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012057 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
12058 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012059 mDispatcher->onWindowInfosChanged(
12060 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012061
12062 touch();
12063
12064 mTouchWindow->consumeAnyMotionDown();
12065}
12066
12067TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
12068 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012069 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12070 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000012071 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012072 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
12073 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012074 mDispatcher->onWindowInfosChanged(
12075 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000012076
12077 touch();
12078
12079 mTouchWindow->assertNoEvents();
12080}
12081
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012082TEST_F(InputDispatcherUntrustedTouchesTest,
12083 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
12084 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012085 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
12086 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012087 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012088 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12089 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012090 mDispatcher->onWindowInfosChanged(
12091 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012092
12093 touch();
12094
12095 mTouchWindow->assertNoEvents();
12096}
12097
12098TEST_F(InputDispatcherUntrustedTouchesTest,
12099 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
12100 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012101 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
12102 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012103 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012104 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12105 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012106 mDispatcher->onWindowInfosChanged(
12107 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012108
12109 touch();
12110
12111 mTouchWindow->consumeAnyMotionDown();
12112}
12113
12114TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
12115 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012116 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
12117 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012118 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012119
12120 touch();
12121
12122 mTouchWindow->consumeAnyMotionDown();
12123}
12124
12125TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
12126 const sp<FakeWindowHandle>& w =
12127 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012128 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000012129
12130 touch();
12131
12132 mTouchWindow->consumeAnyMotionDown();
12133}
12134
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000012135TEST_F(InputDispatcherUntrustedTouchesTest,
12136 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
12137 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
12138 const sp<FakeWindowHandle>& w =
12139 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012140 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000012141
12142 touch();
12143
12144 mTouchWindow->assertNoEvents();
12145}
12146
12147TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
12148 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
12149 const sp<FakeWindowHandle>& w =
12150 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012151 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000012152
12153 touch();
12154
12155 mTouchWindow->consumeAnyMotionDown();
12156}
12157
12158TEST_F(InputDispatcherUntrustedTouchesTest,
12159 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
12160 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
12161 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000012162 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12163 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012164 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000012165
12166 touch();
12167
12168 mTouchWindow->consumeAnyMotionDown();
12169}
12170
12171TEST_F(InputDispatcherUntrustedTouchesTest,
12172 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
12173 const sp<FakeWindowHandle>& w1 =
12174 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
12175 OPACITY_BELOW_THRESHOLD);
12176 const sp<FakeWindowHandle>& w2 =
12177 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
12178 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012179 mDispatcher->onWindowInfosChanged(
12180 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000012181
12182 touch();
12183
12184 mTouchWindow->assertNoEvents();
12185}
12186
12187/**
12188 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
12189 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
12190 * (which alone would result in allowing touches) does not affect the blocking behavior.
12191 */
12192TEST_F(InputDispatcherUntrustedTouchesTest,
12193 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
12194 const sp<FakeWindowHandle>& wB =
12195 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
12196 OPACITY_BELOW_THRESHOLD);
12197 const sp<FakeWindowHandle>& wC =
12198 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
12199 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012200 mDispatcher->onWindowInfosChanged(
12201 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000012202
12203 touch();
12204
12205 mTouchWindow->assertNoEvents();
12206}
12207
12208/**
12209 * This test is testing that a window from a different UID but with same application token doesn't
12210 * block the touch. Apps can share the application token for close UI collaboration for example.
12211 */
12212TEST_F(InputDispatcherUntrustedTouchesTest,
12213 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
12214 const sp<FakeWindowHandle>& w =
12215 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
12216 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012217 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000012218
12219 touch();
12220
12221 mTouchWindow->consumeAnyMotionDown();
12222}
12223
arthurhungb89ccb02020-12-30 16:19:01 +080012224class InputDispatcherDragTests : public InputDispatcherTest {
12225protected:
12226 std::shared_ptr<FakeApplicationHandle> mApp;
12227 sp<FakeWindowHandle> mWindow;
12228 sp<FakeWindowHandle> mSecondWindow;
12229 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012230 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012231 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
12232 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080012233
12234 void SetUp() override {
12235 InputDispatcherTest::SetUp();
12236 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012237 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
12238 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080012239 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080012240
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012241 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
12242 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080012243 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080012244
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012245 mSpyWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow",
12246 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012247 mSpyWindow->setSpy(true);
12248 mSpyWindow->setTrustedOverlay(true);
12249 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
12250
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012251 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012252 mDispatcher->onWindowInfosChanged(
12253 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
12254 {},
12255 0,
12256 0});
arthurhungb89ccb02020-12-30 16:19:01 +080012257 }
12258
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012259 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
12260 switch (fromSource) {
12261 case AINPUT_SOURCE_TOUCHSCREEN:
12262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012263 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012264 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012265 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12266 break;
12267 case AINPUT_SOURCE_STYLUS:
12268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012269 injectMotionEvent(*mDispatcher,
12270 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12271 AINPUT_SOURCE_STYLUS)
12272 .buttonState(
12273 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
12274 .pointer(PointerBuilder(0, ToolType::STYLUS)
12275 .x(50)
12276 .y(50))
12277 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012278 break;
12279 case AINPUT_SOURCE_MOUSE:
12280 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012281 injectMotionEvent(*mDispatcher,
12282 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12283 AINPUT_SOURCE_MOUSE)
12284 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
12285 .pointer(PointerBuilder(MOUSE_POINTER_ID,
12286 ToolType::MOUSE)
12287 .x(50)
12288 .y(50))
12289 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012290 break;
12291 default:
12292 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
12293 }
arthurhungb89ccb02020-12-30 16:19:01 +080012294
12295 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012296 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012297 // Spy window should also receive motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012298 mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012299 }
12300
12301 // Start performing drag, we will create a drag window and transfer touch to it.
12302 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
12303 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012304 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000012305 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012306 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000012307 }
arthurhungb89ccb02020-12-30 16:19:01 +080012308
12309 // The drag window covers the entire display
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012310 mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow",
12311 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012312 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012313 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
12314 *mWindow->getInfo(), *mSecondWindow->getInfo()},
12315 {},
12316 0,
12317 0});
arthurhungb89ccb02020-12-30 16:19:01 +080012318
12319 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000012320 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000012321 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
12322 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000012323 if (transferred) {
12324 mWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012325 mDragWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
12326 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000012327 }
12328 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080012329 }
12330};
12331
12332TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012333 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080012334
12335 // Move on window.
12336 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012337 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012338 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012339 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012340 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12341 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012342 mWindow->consumeDragEvent(false, 50, 50);
12343 mSecondWindow->assertNoEvents();
12344
12345 // Move to another window.
12346 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012347 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012348 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012349 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012350 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12351 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012352 mWindow->consumeDragEvent(true, 150, 50);
12353 mSecondWindow->consumeDragEvent(false, 50, 50);
12354
12355 // Move back to original window.
12356 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012357 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012358 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012359 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012360 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12361 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012362 mWindow->consumeDragEvent(false, 50, 50);
12363 mSecondWindow->consumeDragEvent(true, -50, 50);
12364
12365 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012366 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012367 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080012368 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012369 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080012370 mWindow->assertNoEvents();
12371 mSecondWindow->assertNoEvents();
12372}
12373
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012374TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012375 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012376
12377 // No cancel event after drag start
12378 mSpyWindow->assertNoEvents();
12379
12380 const MotionEvent secondFingerDownEvent =
12381 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12382 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012383 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12384 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012385 .build();
12386 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012387 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000012388 InputEventInjectionSync::WAIT_FOR_RESULT))
12389 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12390
12391 // Receives cancel for first pointer after next pointer down
12392 mSpyWindow->consumeMotionCancel();
12393 mSpyWindow->consumeMotionDown();
12394
12395 mSpyWindow->assertNoEvents();
12396}
12397
arthurhungf452d0b2021-01-06 00:19:52 +080012398TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012399 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080012400
12401 // Move on window.
12402 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012403 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012404 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080012405 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012406 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12407 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080012408 mWindow->consumeDragEvent(false, 50, 50);
12409 mSecondWindow->assertNoEvents();
12410
12411 // Move to another window.
12412 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012413 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012414 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080012415 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012416 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12417 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080012418 mWindow->consumeDragEvent(true, 150, 50);
12419 mSecondWindow->consumeDragEvent(false, 50, 50);
12420
12421 // drop to another window.
12422 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012423 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080012424 {150, 50}))
12425 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012426 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012427 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080012428 mWindow->assertNoEvents();
12429 mSecondWindow->assertNoEvents();
12430}
12431
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012432TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
12433 startDrag();
12434
12435 // No cancel event after drag start
12436 mSpyWindow->assertNoEvents();
12437
12438 const MotionEvent secondFingerDownEvent =
12439 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12440 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12441 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12442 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
12443 .build();
12444 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12445 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12446 InputEventInjectionSync::WAIT_FOR_RESULT))
12447 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12448
12449 // Receives cancel for first pointer after next pointer down
12450 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080012451 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012452 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
12453
12454 mSpyWindow->assertNoEvents();
12455
12456 // Spy window calls pilfer pointers
12457 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
12458 mDragWindow->assertNoEvents();
12459
12460 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080012461 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012462 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
12463 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
12464 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
12465 .build();
12466 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080012467 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012468 InputEventInjectionSync::WAIT_FOR_RESULT))
12469 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12470
12471 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000012472 mDragWindow->consumeMotionEvent(
12473 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000012474 mDragWindow->assertNoEvents();
12475}
12476
arthurhung6d4bed92021-03-17 11:59:33 +080012477TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012478 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080012479
12480 // Move on window and keep button pressed.
12481 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012482 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012483 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
12484 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012485 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012486 .build()))
12487 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012488 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12489 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012490 mWindow->consumeDragEvent(false, 50, 50);
12491 mSecondWindow->assertNoEvents();
12492
12493 // Move to another window and release button, expect to drop item.
12494 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012495 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012496 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
12497 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012498 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012499 .build()))
12500 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012501 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12502 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012503 mWindow->assertNoEvents();
12504 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012505 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080012506
12507 // nothing to the window.
12508 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012509 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080012510 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
12511 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012512 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080012513 .build()))
12514 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012515 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080012516 mWindow->assertNoEvents();
12517 mSecondWindow->assertNoEvents();
12518}
12519
Arthur Hung54745652022-04-20 07:17:41 +000012520TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012521 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080012522
12523 // Set second window invisible.
12524 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012525 mDispatcher->onWindowInfosChanged(
12526 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080012527
12528 // Move on window.
12529 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012530 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012531 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080012532 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012533 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12534 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012535 mWindow->consumeDragEvent(false, 50, 50);
12536 mSecondWindow->assertNoEvents();
12537
12538 // Move to another window.
12539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012540 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012541 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080012542 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012543 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12544 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012545 mWindow->consumeDragEvent(true, 150, 50);
12546 mSecondWindow->assertNoEvents();
12547
12548 // drop to another window.
12549 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012550 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080012551 {150, 50}))
12552 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012553 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012554 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012555 mWindow->assertNoEvents();
12556 mSecondWindow->assertNoEvents();
12557}
12558
Arthur Hung54745652022-04-20 07:17:41 +000012559TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012560 // Ensure window could track pointerIds if it didn't support split touch.
12561 mWindow->setPreventSplitting(true);
12562
Arthur Hung54745652022-04-20 07:17:41 +000012563 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012564 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12565 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000012566 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012567 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012568
12569 const MotionEvent secondFingerDownEvent =
12570 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012571 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000012572 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012573 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12574 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012575 .build();
12576 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012577 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012578 InputEventInjectionSync::WAIT_FOR_RESULT))
12579 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000012580 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000012581
12582 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012583 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000012584}
12585
12586TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
12587 // First down on second window.
12588 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012589 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12590 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000012591 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12592
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012593 mSecondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012594
12595 // Second down on first window.
12596 const MotionEvent secondFingerDownEvent =
12597 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012598 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000012599 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012600 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12601 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012602 .build();
12603 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012604 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012605 InputEventInjectionSync::WAIT_FOR_RESULT))
12606 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012607 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12608 mSecondWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012609
12610 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012611 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000012612
12613 // Move on window.
12614 const MotionEvent secondFingerMoveEvent =
12615 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12616 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012617 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12618 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012619 .build();
12620 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012621 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012622 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012623 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12624 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000012625 mWindow->consumeDragEvent(false, 50, 50);
12626 mSecondWindow->consumeMotionMove();
12627
12628 // Release the drag pointer should perform drop.
12629 const MotionEvent secondFingerUpEvent =
12630 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12631 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012632 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12633 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012634 .build();
12635 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012636 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012637 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012638 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012639 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000012640 mWindow->assertNoEvents();
12641 mSecondWindow->consumeMotionMove();
12642}
12643
Arthur Hung3915c1f2022-05-31 07:17:17 +000012644TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012645 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000012646
12647 // Update window of second display.
12648 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012649 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012650 mDispatcher->onWindowInfosChanged(
12651 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12652 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12653 {},
12654 0,
12655 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012656
12657 // Let second display has a touch state.
12658 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012659 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012660 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12661 AINPUT_SOURCE_TOUCHSCREEN)
12662 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012663 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012664 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000012665 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012666 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012667 mDispatcher->onWindowInfosChanged(
12668 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12669 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12670 {},
12671 0,
12672 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012673
12674 // Move on window.
12675 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012676 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012677 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012678 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012679 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12680 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012681 mWindow->consumeDragEvent(false, 50, 50);
12682 mSecondWindow->assertNoEvents();
12683
12684 // Move to another window.
12685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012686 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012687 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012689 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12690 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012691 mWindow->consumeDragEvent(true, 150, 50);
12692 mSecondWindow->consumeDragEvent(false, 50, 50);
12693
12694 // drop to another window.
12695 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012696 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012697 {150, 50}))
12698 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012699 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012700 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000012701 mWindow->assertNoEvents();
12702 mSecondWindow->assertNoEvents();
12703}
12704
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012705TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
12706 startDrag(true, AINPUT_SOURCE_MOUSE);
12707 // Move on window.
12708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012709 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012710 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12711 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012712 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012713 .x(50)
12714 .y(50))
12715 .build()))
12716 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012717 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12718 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012719 mWindow->consumeDragEvent(false, 50, 50);
12720 mSecondWindow->assertNoEvents();
12721
12722 // Move to another window.
12723 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012724 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012725 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12726 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012727 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012728 .x(150)
12729 .y(50))
12730 .build()))
12731 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012732 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12733 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012734 mWindow->consumeDragEvent(true, 150, 50);
12735 mSecondWindow->consumeDragEvent(false, 50, 50);
12736
12737 // drop to another window.
12738 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012739 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012740 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
12741 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012742 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012743 .x(150)
12744 .y(50))
12745 .build()))
12746 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012747 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012748 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012749 mWindow->assertNoEvents();
12750 mSecondWindow->assertNoEvents();
12751}
12752
Linnan Li5af92f92023-07-14 14:36:22 +080012753/**
12754 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
12755 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
12756 */
12757TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
12758 // Down on second window
12759 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012760 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12761 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012762 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12763
12764 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
12765 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
12766
12767 // Down on first window
12768 const MotionEvent secondFingerDownEvent =
12769 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012770 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012771 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12772 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12773 .build();
12774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12775 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12776 InputEventInjectionSync::WAIT_FOR_RESULT))
12777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12778 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12779 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
12780 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
12781
12782 // Start drag on first window
12783 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
12784
12785 // Trigger cancel
12786 mDispatcher->cancelCurrentTouch();
12787 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012788 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +000012789 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080012790 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
12791
12792 ASSERT_TRUE(mDispatcher->waitForIdle());
12793 // The D&D finished with nullptr
12794 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
12795
12796 // Remove drag window
12797 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
12798
12799 // Inject a simple gesture, ensure dispatcher not crashed
12800 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012801 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12802 ui::LogicalDisplayId::DEFAULT, PointF{50, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012803 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12804 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12805
12806 const MotionEvent moveEvent =
12807 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012808 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012809 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12810 .build();
12811 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12812 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
12813 InputEventInjectionSync::WAIT_FOR_RESULT))
12814 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12815 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
12816
12817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012818 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Li5af92f92023-07-14 14:36:22 +080012819 {50, 50}))
12820 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12821 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
12822}
12823
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012824TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
12825 // Start hovering over the window.
12826 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12827 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012828 ui::LogicalDisplayId::DEFAULT, {50, 50}));
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012829
12830 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12831 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12832
12833 ASSERT_FALSE(startDrag(/*sendDown=*/false))
12834 << "Drag and drop should not work with a hovering pointer";
12835}
12836
Vishnu Nair062a8672021-09-03 16:07:44 -070012837class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
12838
12839TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
12840 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012841 sp<FakeWindowHandle> window =
12842 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12843 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012844 window->setDropInput(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012845 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012846 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012847 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012848 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012849 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012850
12851 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012852 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012853 window->assertNoEvents();
12854
Prabir Pradhan678438e2023-04-13 19:32:51 +000012855 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012856 AINPUT_SOURCE_TOUCHSCREEN,
12857 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012858 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012859 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080012860 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070012861 window->assertNoEvents();
12862
12863 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012864 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012865 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012866
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012867 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12868 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012869
Prabir Pradhan678438e2023-04-13 19:32:51 +000012870 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012871 AINPUT_SOURCE_TOUCHSCREEN,
12872 ui::LogicalDisplayId::DEFAULT));
12873 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012874 window->assertNoEvents();
12875}
12876
12877TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
12878 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12879 std::make_shared<FakeApplicationHandle>();
12880 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012881 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012882 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012883 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012884 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012885 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012886 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012887 sp<FakeWindowHandle> window =
12888 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12889 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012890 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012891 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012892 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012893 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012894 mDispatcher->onWindowInfosChanged(
12895 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012896 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012897 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012898
12899 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012900 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012901 window->assertNoEvents();
12902
Prabir Pradhan678438e2023-04-13 19:32:51 +000012903 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012904 AINPUT_SOURCE_TOUCHSCREEN,
12905 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012906 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012907 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012908 window->assertNoEvents();
12909
12910 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012911 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012912 mDispatcher->onWindowInfosChanged(
12913 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012914
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012915 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12916 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012917
Prabir Pradhan678438e2023-04-13 19:32:51 +000012918 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012919 AINPUT_SOURCE_TOUCHSCREEN,
12920 ui::LogicalDisplayId::DEFAULT));
12921 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
12922 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Vishnu Nair062a8672021-09-03 16:07:44 -070012923 window->assertNoEvents();
12924}
12925
12926TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
12927 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12928 std::make_shared<FakeApplicationHandle>();
12929 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012930 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012931 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012932 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012933 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012934 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012935 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012936 sp<FakeWindowHandle> window =
12937 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12938 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012939 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012940 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012941 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012942 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012943 mDispatcher->onWindowInfosChanged(
12944 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012945 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012946 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012947
12948 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012949 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012950 window->assertNoEvents();
12951
Prabir Pradhan678438e2023-04-13 19:32:51 +000012952 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012953 AINPUT_SOURCE_TOUCHSCREEN,
12954 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012955 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012956 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012957 window->assertNoEvents();
12958
12959 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012960 mDispatcher->onWindowInfosChanged(
12961 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012962
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012963 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12964 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012965
Prabir Pradhan678438e2023-04-13 19:32:51 +000012966 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012967 AINPUT_SOURCE_TOUCHSCREEN,
12968 ui::LogicalDisplayId::DEFAULT));
12969 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012970 window->assertNoEvents();
12971}
12972
Antonio Kantekf16f2832021-09-28 04:39:20 +000012973class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
12974protected:
12975 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000012976 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012977 sp<FakeWindowHandle> mWindow;
12978 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000012979 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012980
12981 void SetUp() override {
12982 InputDispatcherTest::SetUp();
12983
12984 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000012985 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012986 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
12987 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012988 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012989 setFocusedWindow(mWindow);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012990 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
12991 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012992 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000012993 mThirdWindow =
12994 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
12995 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
12996 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012997
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012998 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012999 mDispatcher->onWindowInfosChanged(
13000 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
13001 {},
13002 0,
13003 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000013004 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000013005 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000013006
Antonio Kantek15beb512022-06-13 22:35:41 +000013007 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000013008 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013009 WINDOW_UID, /*hasPermission=*/true,
13010 ui::LogicalDisplayId::DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070013011 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
13012 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000013013 mThirdWindow->assertNoEvents();
13014 }
13015
13016 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
13017 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000013018 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000013019 SECOND_DISPLAY_ID)) {
13020 mWindow->assertNoEvents();
13021 mSecondWindow->assertNoEvents();
13022 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070013023 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000013024 }
13025
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013026 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000013027 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070013028 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013029 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000013030 mWindow->consumeTouchModeEvent(inTouchMode);
13031 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000013032 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000013033 }
13034};
13035
Antonio Kantek26defcf2022-02-08 01:12:27 +000013036TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080013037 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000013038 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
13039 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000013040 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000013041}
13042
Antonio Kantek26defcf2022-02-08 01:12:27 +000013043TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
13044 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013045 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013046 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013047 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000013048 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000013049 ownerUid, /*hasPermission=*/false,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013050 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000013051 mWindow->assertNoEvents();
13052 mSecondWindow->assertNoEvents();
13053}
13054
13055TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
13056 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013057 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013058 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013059 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000013060 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000013061 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000013062}
13063
Antonio Kantekf16f2832021-09-28 04:39:20 +000013064TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080013065 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000013066 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
13067 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013068 /*hasPermission=*/true,
13069 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000013070 mWindow->assertNoEvents();
13071 mSecondWindow->assertNoEvents();
13072}
13073
Antonio Kantek15beb512022-06-13 22:35:41 +000013074TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
13075 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
13076 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
13077 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000013078 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000013079 mWindow->assertNoEvents();
13080 mSecondWindow->assertNoEvents();
13081 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
13082}
13083
Antonio Kantek48710e42022-03-24 14:19:30 -070013084TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
13085 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013087 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070013088 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013089 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Antonio Kantek48710e42022-03-24 14:19:30 -070013090
13091 // Then remove focus.
13092 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013093 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070013094
13095 // Assert that caller can switch touch mode by owning one of the last interacted window.
13096 const WindowInfo& windowInfo = *mWindow->getInfo();
13097 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
13098 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013099 /*hasPermission=*/false,
13100 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070013101}
13102
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013103class InputDispatcherSpyWindowTest : public InputDispatcherTest {
13104public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013105 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013106 std::shared_ptr<FakeApplicationHandle> application =
13107 std::make_shared<FakeApplicationHandle>();
13108 std::string name = "Fake Spy ";
13109 name += std::to_string(mSpyCount++);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013110 sp<FakeWindowHandle> spy =
13111 sp<FakeWindowHandle>::make(application, mDispatcher, name.c_str(),
13112 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013113 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080013114 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013115 return spy;
13116 }
13117
13118 sp<FakeWindowHandle> createForeground() {
13119 std::shared_ptr<FakeApplicationHandle> application =
13120 std::make_shared<FakeApplicationHandle>();
13121 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013122 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013123 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013124 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013125 return window;
13126 }
13127
13128private:
13129 int mSpyCount{0};
13130};
13131
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013132using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013133/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080013134 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
13135 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013136TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070013137 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013138 ScopedSilentDeath _silentDeath;
13139
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013140 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080013141 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013142 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080013143 ".* not a trusted overlay");
13144}
13145
13146/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013147 * Input injection into a display with a spy window but no foreground windows should succeed.
13148 */
13149TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013150 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013151 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013152
13153 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013154 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13155 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013156 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013157 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013158}
13159
13160/**
13161 * Verify the order in which different input windows receive events. The touched foreground window
13162 * (if there is one) should always receive the event first. When there are multiple spy windows, the
13163 * spy windows will receive the event according to their Z-order, where the top-most spy window will
13164 * receive events before ones belows it.
13165 *
13166 * Here, we set up a scenario with four windows in the following Z order from the top:
13167 * spy1, spy2, window, spy3.
13168 * We then inject an event and verify that the foreground "window" receives it first, followed by
13169 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
13170 * window.
13171 */
13172TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
13173 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013174 auto spy1 = createSpy();
13175 auto spy2 = createSpy();
13176 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013177 mDispatcher->onWindowInfosChanged(
13178 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013179 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
13180 const size_t numChannels = channels.size();
13181
Michael Wright8e9a8562022-02-09 13:44:29 +000013182 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013183 if (!epollFd.ok()) {
13184 FAIL() << "Failed to create epoll fd";
13185 }
13186
13187 for (size_t i = 0; i < numChannels; i++) {
13188 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
13189 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
13190 FAIL() << "Failed to add fd to epoll";
13191 }
13192 }
13193
13194 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013195 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13196 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013197 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13198
13199 std::vector<size_t> eventOrder;
13200 std::vector<struct epoll_event> events(numChannels);
13201 for (;;) {
13202 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
13203 (100ms).count());
13204 if (nFds < 0) {
13205 FAIL() << "Failed to call epoll_wait";
13206 }
13207 if (nFds == 0) {
13208 break; // epoll_wait timed out
13209 }
13210 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070013211 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070013212 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013213 channels[i]->consumeMotionDown();
13214 }
13215 }
13216
13217 // Verify the order in which the events were received.
13218 EXPECT_EQ(3u, eventOrder.size());
13219 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
13220 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
13221 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
13222}
13223
13224/**
13225 * A spy window using the NOT_TOUCHABLE flag does not receive events.
13226 */
13227TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
13228 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013229 auto spy = createSpy();
13230 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013231 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013232
13233 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013234 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13235 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013236 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013237 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013238 spy->assertNoEvents();
13239}
13240
13241/**
13242 * A spy window will only receive gestures that originate within its touchable region. Gestures that
13243 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
13244 * to the window.
13245 */
13246TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
13247 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013248 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013249 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013250 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013251
13252 // Inject an event outside the spy window's touchable region.
13253 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013254 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13255 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013256 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13257 window->consumeMotionDown();
13258 spy->assertNoEvents();
13259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013260 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13261 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013262 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13263 window->consumeMotionUp();
13264 spy->assertNoEvents();
13265
13266 // Inject an event inside the spy window's touchable region.
13267 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013268 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13269 ui::LogicalDisplayId::DEFAULT, {5, 10}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013270 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13271 window->consumeMotionDown();
13272 spy->consumeMotionDown();
13273}
13274
13275/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013276 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080013277 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013278 */
13279TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
13280 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013281 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013282 auto spy = createSpy();
13283 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013284 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013285 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013286 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013287
13288 // Inject an event outside the spy window's frame and touchable region.
13289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013290 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13291 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013292 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13293 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080013294 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013295}
13296
13297/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013298 * Even when a spy window spans over multiple foreground windows, the spy should receive all
13299 * pointers that are down within its bounds.
13300 */
13301TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
13302 auto windowLeft = createForeground();
13303 windowLeft->setFrame({0, 0, 100, 200});
13304 auto windowRight = createForeground();
13305 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013306 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013307 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013308 mDispatcher->onWindowInfosChanged(
13309 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013310
13311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013312 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13313 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013314 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13315 windowLeft->consumeMotionDown();
13316 spy->consumeMotionDown();
13317
13318 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080013319 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013320 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013321 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13322 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013323 .build();
13324 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013325 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013326 InputEventInjectionSync::WAIT_FOR_RESULT))
13327 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13328 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000013329 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013330}
13331
13332/**
13333 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
13334 * the spy should receive the second pointer with ACTION_DOWN.
13335 */
13336TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
13337 auto window = createForeground();
13338 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013339 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013340 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013341 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013342
13343 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013344 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13345 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013346 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13347 window->consumeMotionDown();
13348 spyRight->assertNoEvents();
13349
13350 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080013351 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013352 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013353 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13354 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013355 .build();
13356 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013357 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013358 InputEventInjectionSync::WAIT_FOR_RESULT))
13359 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000013360 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080013361 spyRight->consumeMotionDown();
13362}
13363
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013364/**
13365 * The spy window should not be able to affect whether or not touches are split. Only the foreground
13366 * windows should be allowed to control split touch.
13367 */
13368TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080013369 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013370 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013371 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080013372 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013373
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013374 auto window = createForeground();
13375 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013376
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013377 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013378
13379 // First finger down, no window touched.
13380 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013381 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13382 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013383 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013384 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013385 window->assertNoEvents();
13386
13387 // Second finger down on window, the window should receive touch down.
13388 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080013389 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013390 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013391 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013392 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13393 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013394 .build();
13395 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013396 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013397 InputEventInjectionSync::WAIT_FOR_RESULT))
13398 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13399
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013400 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000013401 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013402}
13403
13404/**
13405 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
13406 * do not receive key events.
13407 */
13408TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013409 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013410 spy->setFocusable(false);
13411
13412 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013413 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013414 setFocusedWindow(window);
13415 window->consumeFocusEvent(true);
13416
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013417 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013418 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013419 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013420
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013422 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013423 window->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080013424
13425 spy->assertNoEvents();
13426}
13427
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013428using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
13429
13430/**
13431 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
13432 * are currently sent to any other windows - including other spy windows - will also be cancelled.
13433 */
13434TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
13435 auto window = createForeground();
13436 auto spy1 = createSpy();
13437 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013438 mDispatcher->onWindowInfosChanged(
13439 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013440
13441 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013442 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13443 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013444 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13445 window->consumeMotionDown();
13446 spy1->consumeMotionDown();
13447 spy2->consumeMotionDown();
13448
13449 // Pilfer pointers from the second spy window.
13450 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
13451 spy2->assertNoEvents();
13452 spy1->consumeMotionCancel();
13453 window->consumeMotionCancel();
13454
13455 // The rest of the gesture should only be sent to the second spy window.
13456 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013457 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013458 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013459 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13460 spy2->consumeMotionMove();
13461 spy1->assertNoEvents();
13462 window->assertNoEvents();
13463}
13464
13465/**
13466 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
13467 * in the middle of the gesture.
13468 */
13469TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
13470 auto window = createForeground();
13471 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013472 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013473
13474 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013475 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13476 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013477 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013478 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13479 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013480
13481 window->releaseChannel();
13482
13483 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13484
13485 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013486 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13487 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013488 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013489 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013490}
13491
13492/**
13493 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
13494 * the spy, but not to any other windows.
13495 */
13496TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
13497 auto spy = createSpy();
13498 auto window = createForeground();
13499
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013500 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013501
13502 // First finger down on the window and the spy.
13503 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013504 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13505 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013506 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13507 spy->consumeMotionDown();
13508 window->consumeMotionDown();
13509
13510 // Spy window pilfers the pointers.
13511 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13512 window->consumeMotionCancel();
13513
13514 // Second finger down on the window and spy, but the window should not receive the pointer down.
13515 const MotionEvent secondFingerDownEvent =
13516 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013517 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013518 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013519 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13520 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013521 .build();
13522 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013523 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013524 InputEventInjectionSync::WAIT_FOR_RESULT))
13525 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13526
Harry Cutts33476232023-01-30 19:57:29 +000013527 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013528
13529 // Third finger goes down outside all windows, so injection should fail.
13530 const MotionEvent thirdFingerDownEvent =
13531 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013532 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013533 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013534 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13535 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
13536 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013537 .build();
13538 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013539 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013540 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080013541 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013542
13543 spy->assertNoEvents();
13544 window->assertNoEvents();
13545}
13546
13547/**
13548 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
13549 */
13550TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
13551 auto spy = createSpy();
13552 spy->setFrame(Rect(0, 0, 100, 100));
13553 auto window = createForeground();
13554 window->setFrame(Rect(0, 0, 200, 200));
13555
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013556 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013557
13558 // First finger down on the window only
13559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013560 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13561 ui::LogicalDisplayId::DEFAULT, {150, 150}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013562 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13563 window->consumeMotionDown();
13564
13565 // Second finger down on the spy and window
13566 const MotionEvent secondFingerDownEvent =
13567 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013568 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013569 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013570 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13571 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013572 .build();
13573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013574 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013575 InputEventInjectionSync::WAIT_FOR_RESULT))
13576 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13577 spy->consumeMotionDown();
13578 window->consumeMotionPointerDown(1);
13579
13580 // Third finger down on the spy and window
13581 const MotionEvent thirdFingerDownEvent =
13582 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013583 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013584 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013585 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13586 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
13587 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013588 .build();
13589 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013590 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013591 InputEventInjectionSync::WAIT_FOR_RESULT))
13592 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13593 spy->consumeMotionPointerDown(1);
13594 window->consumeMotionPointerDown(2);
13595
13596 // Spy window pilfers the pointers.
13597 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +000013598 window->consumeMotionPointerUp(/*pointerIdx=*/2,
13599 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13600 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13601 WithPointerCount(3)));
13602 window->consumeMotionPointerUp(/*pointerIdx=*/1,
13603 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13604 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13605 WithPointerCount(2)));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013606
13607 spy->assertNoEvents();
13608 window->assertNoEvents();
13609}
13610
13611/**
13612 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
13613 * other windows should be canceled. If this results in the cancellation of all pointers for some
13614 * window, then that window should receive ACTION_CANCEL.
13615 */
13616TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
13617 auto spy = createSpy();
13618 spy->setFrame(Rect(0, 0, 100, 100));
13619 auto window = createForeground();
13620 window->setFrame(Rect(0, 0, 200, 200));
13621
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013622 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013623
13624 // First finger down on both spy and window
13625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013626 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13627 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013628 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13629 window->consumeMotionDown();
13630 spy->consumeMotionDown();
13631
13632 // Second finger down on the spy and window
13633 const MotionEvent secondFingerDownEvent =
13634 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013635 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013636 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013637 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13638 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013639 .build();
13640 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013641 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013642 InputEventInjectionSync::WAIT_FOR_RESULT))
13643 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13644 spy->consumeMotionPointerDown(1);
13645 window->consumeMotionPointerDown(1);
13646
13647 // Spy window pilfers the pointers.
13648 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13649 window->consumeMotionCancel();
13650
13651 spy->assertNoEvents();
13652 window->assertNoEvents();
13653}
13654
13655/**
13656 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
13657 * be sent to other windows
13658 */
13659TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
13660 auto spy = createSpy();
13661 spy->setFrame(Rect(0, 0, 100, 100));
13662 auto window = createForeground();
13663 window->setFrame(Rect(0, 0, 200, 200));
13664
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013665 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013666
13667 // First finger down on both window and spy
13668 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013669 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13670 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13672 window->consumeMotionDown();
13673 spy->consumeMotionDown();
13674
13675 // Spy window pilfers the pointers.
13676 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13677 window->consumeMotionCancel();
13678
13679 // Second finger down on the window only
13680 const MotionEvent secondFingerDownEvent =
13681 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013682 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013683 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013684 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13685 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013686 .build();
13687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013688 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013689 InputEventInjectionSync::WAIT_FOR_RESULT))
13690 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13691 window->consumeMotionDown();
13692 window->assertNoEvents();
13693
13694 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
13695 spy->consumeMotionMove();
13696 spy->assertNoEvents();
13697}
13698
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013699/**
13700 * A window on the left and a window on the right. Also, a spy window that's above all of the
13701 * windows, and spanning both left and right windows.
13702 * Send simultaneous motion streams from two different devices, one to the left window, and another
13703 * to the right window.
13704 * Pilfer from spy window.
13705 * Check that the pilfering only affects the pointers that are actually being received by the spy.
13706 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013707TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer_legacy) {
13708 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013709 sp<FakeWindowHandle> spy = createSpy();
13710 spy->setFrame(Rect(0, 0, 200, 200));
13711 sp<FakeWindowHandle> leftWindow = createForeground();
13712 leftWindow->setFrame(Rect(0, 0, 100, 100));
13713
13714 sp<FakeWindowHandle> rightWindow = createForeground();
13715 rightWindow->setFrame(Rect(100, 0, 200, 100));
13716
13717 constexpr int32_t stylusDeviceId = 1;
13718 constexpr int32_t touchDeviceId = 2;
13719
13720 mDispatcher->onWindowInfosChanged(
13721 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13722
13723 // Stylus down on left window and spy
13724 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13725 .deviceId(stylusDeviceId)
13726 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13727 .build());
13728 leftWindow->consumeMotionEvent(
13729 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13730 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13731
13732 // Finger down on right window and spy - but spy already has stylus
13733 mDispatcher->notifyMotion(
13734 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13735 .deviceId(touchDeviceId)
13736 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13737 .build());
13738 rightWindow->consumeMotionEvent(
13739 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013740 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013741
13742 // Act: pilfer from spy. Spy is currently receiving touch events.
13743 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013744 leftWindow->consumeMotionEvent(
13745 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013746 rightWindow->consumeMotionEvent(
13747 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13748
13749 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
13750 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13751 .deviceId(stylusDeviceId)
13752 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13753 .build());
13754 mDispatcher->notifyMotion(
13755 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13756 .deviceId(touchDeviceId)
13757 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13758 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013759 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013760
13761 spy->assertNoEvents();
13762 leftWindow->assertNoEvents();
13763 rightWindow->assertNoEvents();
13764}
13765
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013766/**
13767 * A window on the left and a window on the right. Also, a spy window that's above all of the
13768 * windows, and spanning both left and right windows.
13769 * Send simultaneous motion streams from two different devices, one to the left window, and another
13770 * to the right window.
13771 * Pilfer from spy window.
13772 * Check that the pilfering affects all of the pointers that are actually being received by the spy.
13773 * The spy should receive both the touch and the stylus events after pilfer.
13774 */
13775TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
13776 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13777 sp<FakeWindowHandle> spy = createSpy();
13778 spy->setFrame(Rect(0, 0, 200, 200));
13779 sp<FakeWindowHandle> leftWindow = createForeground();
13780 leftWindow->setFrame(Rect(0, 0, 100, 100));
13781
13782 sp<FakeWindowHandle> rightWindow = createForeground();
13783 rightWindow->setFrame(Rect(100, 0, 200, 100));
13784
13785 constexpr int32_t stylusDeviceId = 1;
13786 constexpr int32_t touchDeviceId = 2;
13787
13788 mDispatcher->onWindowInfosChanged(
13789 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13790
13791 // Stylus down on left window and spy
13792 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13793 .deviceId(stylusDeviceId)
13794 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13795 .build());
13796 leftWindow->consumeMotionEvent(
13797 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13798 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13799
13800 // Finger down on right window and spy
13801 mDispatcher->notifyMotion(
13802 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13803 .deviceId(touchDeviceId)
13804 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13805 .build());
13806 rightWindow->consumeMotionEvent(
13807 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13808 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13809
13810 // Act: pilfer from spy. Spy is currently receiving touch events.
13811 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13812 leftWindow->consumeMotionEvent(
13813 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
13814 rightWindow->consumeMotionEvent(
13815 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13816
13817 // Continue movements from both stylus and touch. Touch and stylus will be delivered to spy
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013818 // Instead of sending the two MOVE events for each input device together, and then receiving
13819 // them both, process them one at at time. InputConsumer is always in the batching mode, which
13820 // means that the two MOVE events will be initially put into a batch. Once the events are
13821 // batched, the 'consume' call may result in any of the MOVE events to be sent first (depending
13822 // on the implementation of InputConsumer), which would mean that the order of the received
13823 // events could be different depending on whether there are 1 or 2 events pending in the
13824 // InputChannel at the time the test calls 'consume'. To make assertions simpler here, and to
13825 // avoid this confusing behaviour, send and receive each MOVE event separately.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013826 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13827 .deviceId(stylusDeviceId)
13828 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13829 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013830 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013831 mDispatcher->notifyMotion(
13832 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13833 .deviceId(touchDeviceId)
13834 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13835 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013836 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013837
13838 spy->assertNoEvents();
13839 leftWindow->assertNoEvents();
13840 rightWindow->assertNoEvents();
13841}
13842
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000013843TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
13844 auto window = createForeground();
13845 auto spy = createSpy();
13846 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13847
13848 mDispatcher->notifyMotion(
13849 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
13850 .deviceId(1)
13851 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
13852 .build());
13853 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13854 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13855
13856 // Pilfer pointers from the spy window should fail.
13857 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
13858 spy->assertNoEvents();
13859 window->assertNoEvents();
13860}
13861
Prabir Pradhand65552b2021-10-07 11:23:50 -070013862class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
13863public:
13864 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
13865 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13866 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013867 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
13868 "Stylus interceptor window",
13869 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013870 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013871 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013872 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013873 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013874 overlay->setTrustedOverlay(true);
13875
13876 std::shared_ptr<FakeApplicationHandle> application =
13877 std::make_shared<FakeApplicationHandle>();
13878 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013879 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013880 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013881 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013882 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013883
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013884 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013885 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013886 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013887 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013888 return {std::move(overlay), std::move(window)};
13889 }
13890
13891 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000013892 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070013893 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013894 ui::LogicalDisplayId::DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070013895 }
13896
13897 void sendStylusEvent(int32_t action) {
13898 NotifyMotionArgs motionArgs =
13899 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013900 ui::LogicalDisplayId::DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013901 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000013902 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013903 }
13904};
13905
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013906using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
13907
13908TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070013909 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013910 ScopedSilentDeath _silentDeath;
13911
Prabir Pradhand65552b2021-10-07 11:23:50 -070013912 auto [overlay, window] = setupStylusOverlayScenario();
13913 overlay->setTrustedOverlay(false);
13914 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013915 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
13916 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070013917 ".* not a trusted overlay");
13918}
13919
13920TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
13921 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013922 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013923
13924 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13925 overlay->consumeMotionDown();
13926 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13927 overlay->consumeMotionUp();
13928
13929 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13930 window->consumeMotionDown();
13931 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13932 window->consumeMotionUp();
13933
13934 overlay->assertNoEvents();
13935 window->assertNoEvents();
13936}
13937
13938TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
13939 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013940 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013941 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013942
13943 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13944 overlay->consumeMotionDown();
13945 window->consumeMotionDown();
13946 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13947 overlay->consumeMotionUp();
13948 window->consumeMotionUp();
13949
13950 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13951 window->consumeMotionDown();
13952 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13953 window->consumeMotionUp();
13954
13955 overlay->assertNoEvents();
13956 window->assertNoEvents();
13957}
13958
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013959/**
13960 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
13961 * The scenario is as follows:
13962 * - The stylus interceptor overlay is configured as a spy window.
13963 * - The stylus interceptor spy receives the start of a new stylus gesture.
13964 * - It pilfers pointers and then configures itself to no longer be a spy.
13965 * - The stylus interceptor continues to receive the rest of the gesture.
13966 */
13967TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
13968 auto [overlay, window] = setupStylusOverlayScenario();
13969 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013970 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013971
13972 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13973 overlay->consumeMotionDown();
13974 window->consumeMotionDown();
13975
13976 // The interceptor pilfers the pointers.
13977 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
13978 window->consumeMotionCancel();
13979
13980 // The interceptor configures itself so that it is no longer a spy.
13981 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013982 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013983
13984 // It continues to receive the rest of the stylus gesture.
13985 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
13986 overlay->consumeMotionMove();
13987 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13988 overlay->consumeMotionUp();
13989
13990 window->assertNoEvents();
13991}
13992
Prabir Pradhan5735a322022-04-11 17:23:34 +000013993struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013994 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013995 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000013996 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
13997 std::unique_ptr<InputDispatcher>& mDispatcher;
13998
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013999 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000014000 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
14001
14002 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070014003 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014004 ui::LogicalDisplayId::DEFAULT, {100, 200},
Prabir Pradhan5735a322022-04-11 17:23:34 +000014005 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
14006 AMOTION_EVENT_INVALID_CURSOR_POSITION},
14007 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
14008 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
14009 }
14010
14011 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Linnan Li13bf76a2024-05-05 19:18:02 +080014012 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014013 ui::LogicalDisplayId::INVALID,
Prabir Pradhan5735a322022-04-11 17:23:34 +000014014 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000014015 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000014016 mPolicyFlags);
14017 }
14018
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014019 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000014020 std::shared_ptr<FakeApplicationHandle> overlayApplication =
14021 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014022 sp<FakeWindowHandle> window =
14023 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, name,
14024 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000014025 window->setOwnerInfo(mPid, mUid);
14026 return window;
14027 }
14028};
14029
14030using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
14031
14032TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014033 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014034 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014035 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014036
14037 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14038 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14039 window->consumeMotionDown();
14040
14041 setFocusedWindow(window);
14042 window->consumeFocusEvent(true);
14043
14044 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14045 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014046 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000014047}
14048
14049TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014050 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014051 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014052 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014053
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014054 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014055 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
14056 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14057
14058 setFocusedWindow(window);
14059 window->consumeFocusEvent(true);
14060
14061 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
14062 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
14063 window->assertNoEvents();
14064}
14065
14066TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014067 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014068 auto window = owner.createWindow("Owned window");
14069 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014070 spy->setSpy(true);
14071 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014072 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014073
14074 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14075 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14076 spy->consumeMotionDown();
14077 window->consumeMotionDown();
14078}
14079
14080TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014081 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014082 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014083
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014084 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014085 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014086 randosSpy->setSpy(true);
14087 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014088 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014089
14090 // The event is targeted at owner's window, so injection should succeed, but the spy should
14091 // not receive the event.
14092 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14093 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14094 randosSpy->assertNoEvents();
14095 window->consumeMotionDown();
14096}
14097
14098TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014099 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014100 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014101
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014102 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014103 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014104 randosSpy->setSpy(true);
14105 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014106 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014107
14108 // A user that has injection permission can inject into any window.
14109 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070014110 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014111 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan5735a322022-04-11 17:23:34 +000014112 randosSpy->consumeMotionDown();
14113 window->consumeMotionDown();
14114
14115 setFocusedWindow(randosSpy);
14116 randosSpy->consumeFocusEvent(true);
14117
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070014118 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014119 randosSpy->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000014120 window->assertNoEvents();
14121}
14122
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070014123TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014124 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014125 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014126
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000014127 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070014128 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000014129 randosWindow->setFrame(Rect{-10, -10, -5, -5});
14130 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070014131 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000014132
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070014133 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000014134 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
14135 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
14136 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070014137 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000014138}
14139
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014140using InputDispatcherPointerInWindowTest = InputDispatcherTest;
14141
14142TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
14143 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14144
14145 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014146 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014147 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014148 sp<FakeWindowHandle> right =
14149 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14150 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014151 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014152 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
14153 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014154 spy->setFrame(Rect(0, 0, 200, 100));
14155 spy->setTrustedOverlay(true);
14156 spy->setSpy(true);
14157
14158 mDispatcher->onWindowInfosChanged(
14159 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
14160
14161 // Hover into the left window.
14162 mDispatcher->notifyMotion(
14163 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
14164 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
14165 .build());
14166
14167 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14168 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14169
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014170 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14171 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014172 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014173 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14174 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014175 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014176 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14177 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014178 /*pointerId=*/0));
14179
14180 // Hover move to the right window.
14181 mDispatcher->notifyMotion(
14182 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
14183 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
14184 .build());
14185
14186 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14187 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14188 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
14189
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014190 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14191 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014192 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014193 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14194 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014195 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014196 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14197 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014198 /*pointerId=*/0));
14199
14200 // Stop hovering.
14201 mDispatcher->notifyMotion(
14202 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
14203 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
14204 .build());
14205
14206 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14207 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14208
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014209 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14210 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014211 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014212 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14213 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014214 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014215 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14216 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014217 /*pointerId=*/0));
14218}
14219
14220TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
14221 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14222
14223 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014224 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014225 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014226 sp<FakeWindowHandle> right =
14227 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14228 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014229 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014230 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
14231 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014232 spy->setFrame(Rect(0, 0, 200, 100));
14233 spy->setTrustedOverlay(true);
14234 spy->setSpy(true);
14235
14236 mDispatcher->onWindowInfosChanged(
14237 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
14238
14239 // First pointer down on left window.
14240 mDispatcher->notifyMotion(
14241 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
14242 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14243 .build());
14244
14245 left->consumeMotionDown();
14246 spy->consumeMotionDown();
14247
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014248 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14249 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014250 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014251 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14252 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014253 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014254 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14255 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014256 /*pointerId=*/0));
14257
14258 // Second pointer down on right window.
14259 mDispatcher->notifyMotion(
14260 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
14261 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14262 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
14263 .build());
14264
14265 left->consumeMotionMove();
14266 right->consumeMotionDown();
14267 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
14268
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014269 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14270 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014271 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014272 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14273 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014274 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014275 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14276 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014277 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014278 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14279 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014280 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014281 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14282 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014283 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014284 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14285 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014286 /*pointerId=*/1));
14287
14288 // Second pointer up.
14289 mDispatcher->notifyMotion(
14290 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
14291 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14292 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
14293 .build());
14294
14295 left->consumeMotionMove();
14296 right->consumeMotionUp();
14297 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
14298
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014299 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14300 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014301 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014302 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14303 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014304 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014305 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14306 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014307 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014308 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14309 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014310 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014311 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14312 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014313 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014314 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14315 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014316 /*pointerId=*/1));
14317
14318 // First pointer up.
14319 mDispatcher->notifyMotion(
14320 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
14321 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
14322 .build());
14323
14324 left->consumeMotionUp();
14325 spy->consumeMotionUp();
14326
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014327 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14328 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014329 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014330 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
14331 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014332 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014333 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14334 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014335 /*pointerId=*/0));
14336}
14337
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014338TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse_legacy) {
14339 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014340 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14341
14342 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014343 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014344 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014345 sp<FakeWindowHandle> right =
14346 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14347 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014348 right->setFrame(Rect(100, 0, 200, 100));
14349
14350 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
14351
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014352 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14353 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014354 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014355 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14356 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014357 /*pointerId=*/0));
14358
14359 // Hover move into the window.
14360 mDispatcher->notifyMotion(
14361 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14362 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
14363 .rawXCursorPosition(50)
14364 .rawYCursorPosition(50)
14365 .deviceId(DEVICE_ID)
14366 .build());
14367
14368 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14369
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014370 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14371 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014372 /*pointerId=*/0));
14373
14374 // Move the mouse with another device. This cancels the hovering pointer from the first device.
14375 mDispatcher->notifyMotion(
14376 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14377 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
14378 .rawXCursorPosition(51)
14379 .rawYCursorPosition(50)
14380 .deviceId(SECOND_DEVICE_ID)
14381 .build());
14382
14383 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14384 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14385
14386 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
14387 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014388 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14389 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014390 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014391 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014392 SECOND_DEVICE_ID,
14393 /*pointerId=*/0));
14394
14395 // Move the mouse outside the window. Document the current behavior, where the window does not
14396 // receive HOVER_EXIT even though the mouse left the window.
14397 mDispatcher->notifyMotion(
14398 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14399 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
14400 .rawXCursorPosition(150)
14401 .rawYCursorPosition(50)
14402 .deviceId(SECOND_DEVICE_ID)
14403 .build());
14404
14405 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14406 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014407 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14408 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014409 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014410 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000014411 SECOND_DEVICE_ID,
14412 /*pointerId=*/0));
14413}
14414
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014415/**
14416 * TODO(b/313689709) - correctly support multiple mouse devices, because they should be controlling
14417 * the same cursor, and therefore have a shared motion event stream.
14418 */
14419TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
14420 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
14421 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
14422
14423 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014424 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014425 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014426 sp<FakeWindowHandle> right =
14427 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
14428 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014429 right->setFrame(Rect(100, 0, 200, 100));
14430
14431 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
14432
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014433 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14434 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014435 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014436 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
14437 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014438 /*pointerId=*/0));
14439
14440 // Hover move into the window.
14441 mDispatcher->notifyMotion(
14442 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14443 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
14444 .rawXCursorPosition(50)
14445 .rawYCursorPosition(50)
14446 .deviceId(DEVICE_ID)
14447 .build());
14448
14449 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14450
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014451 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14452 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014453 /*pointerId=*/0));
14454
14455 // Move the mouse with another device
14456 mDispatcher->notifyMotion(
14457 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14458 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
14459 .rawXCursorPosition(51)
14460 .rawYCursorPosition(50)
14461 .deviceId(SECOND_DEVICE_ID)
14462 .build());
14463 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14464
14465 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
14466 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014467 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14468 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014469 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014470 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014471 SECOND_DEVICE_ID,
14472 /*pointerId=*/0));
14473
14474 // Move the mouse outside the window. Document the current behavior, where the window does not
14475 // receive HOVER_EXIT even though the mouse left the window.
14476 mDispatcher->notifyMotion(
14477 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14478 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
14479 .rawXCursorPosition(150)
14480 .rawYCursorPosition(50)
14481 .deviceId(SECOND_DEVICE_ID)
14482 .build());
14483
14484 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014485 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14486 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014487 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014488 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014489 SECOND_DEVICE_ID,
14490 /*pointerId=*/0));
14491}
14492
Arpit Singhb65e2bd2024-06-03 09:48:16 +000014493TEST_F(InputDispatcherTest, FocusedDisplayChangeIsNotified) {
14494 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
14495 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
14496}
14497
Garfield Tane84e6f92019-08-29 17:28:41 -070014498} // namespace android::inputdispatcher