blob: aa1462a2ffa72977ea15693ea2a11b79eb718e65 [file] [log] [blame]
Michael Wrightd02c5b62014-02-10 15:10:22 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Garfield Tan0fc2fa72019-08-29 17:22:15 -070017#include "../dispatcher/InputDispatcher.h"
Siarhei Vishniakou2defec02023-06-08 17:24:44 -070018#include "FakeApplicationHandle.h"
Prabir Pradhan81e89fe2024-03-20 21:17:09 +000019#include "FakeInputDispatcherPolicy.h"
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +000020#include "FakeInputTracingBackend.h"
Prabir Pradhanc5340732024-03-20 22:53:52 +000021#include "FakeWindows.h"
Prabir Pradhane3b28dd2023-10-06 04:19:29 +000022#include "TestEventMatchers.h"
Michael Wrightd02c5b62014-02-10 15:10:22 -080023
Cody Heiner166a5af2023-07-07 12:25:00 -070024#include <NotifyArgsBuilders.h>
Prabir Pradhan5893d362023-11-17 04:30:40 +000025#include <android-base/logging.h>
Siarhei Vishniakou1c494c52021-08-11 20:25:01 -070026#include <android-base/properties.h>
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080027#include <android-base/silent_death_test.h>
Garfield Tan1c7bc862020-01-28 13:24:04 -080028#include <android-base/stringprintf.h>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070029#include <android-base/thread_annotations.h>
Robert Carr803535b2018-08-02 16:38:15 -070030#include <binder/Binder.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000031#include <com_android_input_flags.h>
Michael Wright8e9a8562022-02-09 13:44:29 +000032#include <fcntl.h>
Ameer Armalycff4fa52023-10-04 23:45:11 +000033#include <flag_macros.h>
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080034#include <gmock/gmock.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080035#include <gtest/gtest.h>
Siarhei Vishniakou3782af62024-03-07 21:56:39 -080036#include <input/BlockingQueue.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100037#include <input/Input.h>
Siarhei Vishniakou0438ca82024-03-12 14:27:25 -070038#include <input/InputConsumer.h>
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070039#include <input/PrintTools.h>
Michael Wrightd02c5b62014-02-10 15:10:22 -080040#include <linux/input.h>
Prabir Pradhan07e05b62021-11-19 03:57:24 -080041#include <sys/epoll.h>
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -100042
Garfield Tan1c7bc862020-01-28 13:24:04 -080043#include <cinttypes>
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080044#include <compare>
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -070045#include <thread>
Garfield Tan1c7bc862020-01-28 13:24:04 -080046#include <unordered_set>
chaviwd1c23182019-12-20 18:44:56 -080047#include <vector>
Michael Wrightd02c5b62014-02-10 15:10:22 -080048
Garfield Tan1c7bc862020-01-28 13:24:04 -080049using android::base::StringPrintf;
chaviw3277faf2021-05-19 16:45:23 -050050using android::gui::FocusRequest;
51using android::gui::TouchOcclusionMode;
52using android::gui::WindowInfo;
53using android::gui::WindowInfoHandle;
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080054using android::os::InputEventInjectionResult;
55using android::os::InputEventInjectionSync;
Garfield Tan1c7bc862020-01-28 13:24:04 -080056
Garfield Tane84e6f92019-08-29 17:28:41 -070057namespace android::inputdispatcher {
Michael Wrightd02c5b62014-02-10 15:10:22 -080058
Dominik Laskowski2f01d772022-03-23 16:01:29 -070059using namespace ftl::flag_operators;
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -080060using testing::AllOf;
Prabir Pradhan5893d362023-11-17 04:30:40 +000061using testing::Not;
Siarhei Vishniakou85eb5802024-04-01 11:40:59 -070062using testing::Pointee;
63using testing::UnorderedElementsAre;
Dominik Laskowski2f01d772022-03-23 16:01:29 -070064
Siarhei Vishniakouf4043212023-09-18 19:33:03 -070065namespace {
66
Michael Wrightd02c5b62014-02-10 15:10:22 -080067// An arbitrary time value.
Prabir Pradhan5735a322022-04-11 17:23:34 +000068static constexpr nsecs_t ARBITRARY_TIME = 1234;
Michael Wrightd02c5b62014-02-10 15:10:22 -080069
70// An arbitrary device id.
Prabir Pradhan9205e422023-05-16 20:06:13 +000071static constexpr int32_t DEVICE_ID = DEFAULT_DEVICE_ID;
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -080072static constexpr int32_t SECOND_DEVICE_ID = 2;
Michael Wrightd02c5b62014-02-10 15:10:22 -080073
Jeff Brownf086ddb2014-02-11 14:28:48 -080074// An arbitrary display id.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070075constexpr ui::LogicalDisplayId DISPLAY_ID = ui::LogicalDisplayId::DEFAULT;
Linnan Li13bf76a2024-05-05 19:18:02 +080076constexpr ui::LogicalDisplayId SECOND_DISPLAY_ID = ui::LogicalDisplayId{1};
Jeff Brownf086ddb2014-02-11 14:28:48 -080077
Prabir Pradhan8ede1d12023-05-08 19:37:44 +000078// Ensure common actions are interchangeable between keys and motions for convenience.
79static_assert(AMOTION_EVENT_ACTION_DOWN == AKEY_EVENT_ACTION_DOWN);
80static_assert(AMOTION_EVENT_ACTION_UP == AKEY_EVENT_ACTION_UP);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080081static constexpr int32_t ACTION_DOWN = AMOTION_EVENT_ACTION_DOWN;
82static constexpr int32_t ACTION_MOVE = AMOTION_EVENT_ACTION_MOVE;
83static constexpr int32_t ACTION_UP = AMOTION_EVENT_ACTION_UP;
84static constexpr int32_t ACTION_HOVER_ENTER = AMOTION_EVENT_ACTION_HOVER_ENTER;
Siarhei Vishniakoua235c042023-05-02 09:59:09 -070085static constexpr int32_t ACTION_HOVER_MOVE = AMOTION_EVENT_ACTION_HOVER_MOVE;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080086static constexpr int32_t ACTION_HOVER_EXIT = AMOTION_EVENT_ACTION_HOVER_EXIT;
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070087static constexpr int32_t ACTION_SCROLL = AMOTION_EVENT_ACTION_SCROLL;
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -080088static constexpr int32_t ACTION_OUTSIDE = AMOTION_EVENT_ACTION_OUTSIDE;
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080089static constexpr int32_t ACTION_CANCEL = AMOTION_EVENT_ACTION_CANCEL;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -080090/**
91 * The POINTER_DOWN(0) is an unusual, but valid, action. It just means that the new pointer in the
92 * MotionEvent is at the index 0 rather than 1 (or later). That is, the pointer id=0 (which is at
93 * index 0) is the new pointer going down. The same pointer could have been placed at a different
94 * index, and the action would become POINTER_1_DOWN, 2, etc..; these would all be valid. In
95 * general, we try to place pointer id = 0 at the index 0. Of course, this is not possible if
96 * pointer id=0 leaves but the pointer id=1 remains.
97 */
98static constexpr int32_t POINTER_0_DOWN =
99 AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800100static constexpr int32_t POINTER_1_DOWN =
101 AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +0000102static constexpr int32_t POINTER_2_DOWN =
103 AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +0000104static constexpr int32_t POINTER_3_DOWN =
105 AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Arthur Hungc539dbb2022-12-08 07:45:36 +0000106static constexpr int32_t POINTER_0_UP =
107 AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800108static constexpr int32_t POINTER_1_UP =
109 AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Harry Cuttsb166c002023-05-09 13:06:05 +0000110static constexpr int32_t POINTER_2_UP =
111 AMOTION_EVENT_ACTION_POINTER_UP | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800112
Antonio Kantek15beb512022-06-13 22:35:41 +0000113// The default pid and uid for the windows created on the secondary display by the test.
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000114static constexpr gui::Pid SECONDARY_WINDOW_PID{1010};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000115static constexpr gui::Uid SECONDARY_WINDOW_UID{1012};
Antonio Kantek15beb512022-06-13 22:35:41 +0000116
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000117// An arbitrary pid of the gesture monitor window
Prabir Pradhanaeebeb42023-06-13 19:53:03 +0000118static constexpr gui::Pid MONITOR_PID{2001};
Siarhei Vishniakou58cfc602020-12-14 23:21:30 +0000119
Linnan Li72352222024-04-12 18:55:57 +0800120static constexpr int EXPECTED_WALLPAPER_FLAGS =
Arthur Hungc539dbb2022-12-08 07:45:36 +0000121 AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
122
Siarhei Vishniakou56e79092023-02-21 19:13:16 -0800123using ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID;
124
Gang Wang342c9272020-01-13 13:15:04 -0500125/**
126 * Return a DOWN key event with KEYCODE_A.
127 */
128static KeyEvent getTestKeyEvent() {
129 KeyEvent event;
130
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700131 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
132 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
133 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Gang Wang342c9272020-01-13 13:15:04 -0500134 return event;
135}
136
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -0700137/**
138 * Provide a local override for a flag value. The value is restored when the object of this class
139 * goes out of scope.
140 * This class is not intended to be used directly, because its usage is cumbersome.
141 * Instead, a wrapper macro SCOPED_FLAG_OVERRIDE is provided.
142 */
143class ScopedFlagOverride {
144public:
145 ScopedFlagOverride(std::function<bool()> read, std::function<void(bool)> write, bool value)
146 : mInitialValue(read()), mWriteValue(write) {
147 mWriteValue(value);
148 }
149 ~ScopedFlagOverride() { mWriteValue(mInitialValue); }
150
151private:
152 const bool mInitialValue;
153 std::function<void(bool)> mWriteValue;
154};
155
156typedef bool (*readFlagValueFunction)();
157typedef void (*writeFlagValueFunction)(bool);
158
159/**
160 * Use this macro to locally override a flag value.
161 * Example usage:
162 * SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
163 * Note: this works by creating a local variable in your current scope. Don't call this twice for
164 * the same flag, because the variable names will clash!
165 */
166#define SCOPED_FLAG_OVERRIDE(NAME, VALUE) \
167 readFlagValueFunction read##NAME = com::android::input::flags::NAME; \
168 writeFlagValueFunction write##NAME = com::android::input::flags::NAME; \
169 ScopedFlagOverride override##NAME(read##NAME, write##NAME, (VALUE))
170
Siarhei Vishniakouf4043212023-09-18 19:33:03 -0700171} // namespace
Michael Wrightd02c5b62014-02-10 15:10:22 -0800172
Michael Wrightd02c5b62014-02-10 15:10:22 -0800173// --- InputDispatcherTest ---
174
175class InputDispatcherTest : public testing::Test {
176protected:
Prabir Pradhana41d2442023-04-20 21:30:40 +0000177 std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700178 std::unique_ptr<InputDispatcher> mDispatcher;
Prabir Pradhanc5340732024-03-20 22:53:52 +0000179 std::shared_ptr<VerifyingTrace> mVerifyingTrace;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800180
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000181 void SetUp() override {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000182 mVerifyingTrace = std::make_shared<VerifyingTrace>();
183 FakeWindowHandle::sOnEventReceivedCallback = [this](const auto& _1, const auto& _2) {
184 handleEventReceivedByWindow(_1, _2);
185 };
186
Prabir Pradhana41d2442023-04-20 21:30:40 +0000187 mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
Prabir Pradhandc3a2ad2024-02-05 19:03:51 +0000188 mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
189 std::make_unique<FakeInputTracingBackend>(
Prabir Pradhanc5340732024-03-20 22:53:52 +0000190 mVerifyingTrace));
Siarhei Vishniakoua7333112023-10-27 13:33:29 -0700191
Harry Cutts101ee9b2023-07-06 18:04:14 +0000192 mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000193 // Start InputDispatcher thread
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700194 ASSERT_EQ(OK, mDispatcher->start());
Michael Wrightd02c5b62014-02-10 15:10:22 -0800195 }
196
Siarhei Vishniakouf2652122021-03-05 21:39:46 +0000197 void TearDown() override {
Prabir Pradhanc5340732024-03-20 22:53:52 +0000198 ASSERT_NO_FATAL_FAILURE(mVerifyingTrace->verifyExpectedEventsTraced());
199 FakeWindowHandle::sOnEventReceivedCallback = nullptr;
200
Prabir Pradhan3608aad2019-10-02 17:08:26 -0700201 ASSERT_EQ(OK, mDispatcher->stop());
Prabir Pradhana41d2442023-04-20 21:30:40 +0000202 mFakePolicy.reset();
Siarhei Vishniakou18050092021-09-01 13:32:49 -0700203 mDispatcher.reset();
Michael Wrightd02c5b62014-02-10 15:10:22 -0800204 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700205
Prabir Pradhanc5340732024-03-20 22:53:52 +0000206 void handleEventReceivedByWindow(const std::unique_ptr<InputEvent>& event,
207 const gui::WindowInfo& info) {
208 if (!event) {
209 return;
210 }
211
212 switch (event->getType()) {
213 case InputEventType::KEY: {
214 mVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event), info.id);
215 break;
216 }
217 case InputEventType::MOTION: {
218 mVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event),
219 info.id);
220 break;
221 }
222 default:
223 break;
224 }
225 }
226
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700227 /**
228 * Used for debugging when writing the test
229 */
230 void dumpDispatcherState() {
231 std::string dump;
232 mDispatcher->dump(dump);
233 std::stringstream ss(dump);
234 std::string to;
235
236 while (std::getline(ss, to, '\n')) {
237 ALOGE("%s", to.c_str());
238 }
239 }
Vishnu Nair958da932020-08-21 17:12:37 -0700240
Chavi Weingarten847e8512023-03-29 00:26:09 +0000241 void setFocusedWindow(const sp<WindowInfoHandle>& window) {
Vishnu Nair958da932020-08-21 17:12:37 -0700242 FocusRequest request;
243 request.token = window->getToken();
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +0000244 request.windowName = window->getName();
Vishnu Nair958da932020-08-21 17:12:37 -0700245 request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
Linnan Li13bf76a2024-05-05 19:18:02 +0800246 request.displayId = window->getInfo()->displayId.val();
Vishnu Nair958da932020-08-21 17:12:37 -0700247 mDispatcher->setFocusedWindow(request);
248 }
Michael Wrightd02c5b62014-02-10 15:10:22 -0800249};
250
Michael Wrightd02c5b62014-02-10 15:10:22 -0800251TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
252 KeyEvent event;
253
254 // Rejects undefined key actions.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700255 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
256 ui::LogicalDisplayId::INVALID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000257 /*action=*/-1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
Siarhei Vishniakou9c858ac2020-01-23 14:20:11 -0600258 ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800259 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000260 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000261 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800262 << "Should reject key events with undefined action.";
263
264 // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700265 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
266 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0,
267 AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800268 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000269 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000270 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800271 << "Should reject key events with ACTION_MULTIPLE.";
272}
273
274TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
275 MotionEvent event;
276 PointerProperties pointerProperties[MAX_POINTERS + 1];
277 PointerCoords pointerCoords[MAX_POINTERS + 1];
Siarhei Vishniakou01747382022-01-20 13:23:27 -0800278 for (size_t i = 0; i <= MAX_POINTERS; i++) {
Michael Wrightd02c5b62014-02-10 15:10:22 -0800279 pointerProperties[i].clear();
280 pointerProperties[i].id = i;
281 pointerCoords[i].clear();
282 }
283
Siarhei Vishniakou49e59222018-12-28 18:17:15 -0800284 // Some constants commonly used below
285 constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
286 constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
287 constexpr int32_t metaState = AMETA_NONE;
288 constexpr MotionClassification classification = MotionClassification::NONE;
289
chaviw9eaa22c2020-07-01 16:21:27 -0700290 ui::Transform identityTransform;
Michael Wrightd02c5b62014-02-10 15:10:22 -0800291 // Rejects undefined motion actions.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800292 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000293 /*action=*/-1, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700294 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700295 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
296 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000297 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800298 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000299 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000300 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800301 << "Should reject motion events with undefined action.";
302
303 // Rejects pointer down with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800304 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800305 POINTER_1_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
306 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
307 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
308 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000309 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800310 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000311 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000312 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800313 << "Should reject motion events with pointer down index too large.";
314
Garfield Tanfbe732e2020-01-24 11:26:14 -0800315 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700316 AMOTION_EVENT_ACTION_POINTER_DOWN |
317 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700318 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
319 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700320 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000321 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800322 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000323 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000324 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800325 << "Should reject motion events with pointer down index too small.";
326
327 // Rejects pointer up with invalid index.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800328 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800329 POINTER_1_UP, 0, 0, edgeFlags, metaState, 0, classification, identityTransform,
330 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
331 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
332 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000333 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800334 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000335 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000336 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800337 << "Should reject motion events with pointer up index too large.";
338
Garfield Tanfbe732e2020-01-24 11:26:14 -0800339 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
Garfield Tan00f511d2019-06-12 16:55:40 -0700340 AMOTION_EVENT_ACTION_POINTER_UP |
341 (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
chaviw9eaa22c2020-07-01 16:21:27 -0700342 0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
343 AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700344 identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000345 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800346 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000347 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000348 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800349 << "Should reject motion events with pointer up index too small.";
350
351 // Rejects motion events with invalid number of pointers.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800352 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
353 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700354 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700355 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
356 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000357 /*pointerCount=*/0, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800358 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000359 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000360 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800361 << "Should reject motion events with 0 pointers.";
362
Garfield Tanfbe732e2020-01-24 11:26:14 -0800363 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
364 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700365 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700366 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
367 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000368 /*pointerCount=*/MAX_POINTERS + 1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800369 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000370 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000371 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800372 << "Should reject motion events with more than MAX_POINTERS pointers.";
373
374 // Rejects motion events with invalid pointer ids.
375 pointerProperties[0].id = -1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800376 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
377 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700378 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700379 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
380 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000381 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800382 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000383 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000384 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800385 << "Should reject motion events with pointer ids less than 0.";
386
387 pointerProperties[0].id = MAX_POINTER_ID + 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800388 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
389 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700390 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700391 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
392 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000393 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800394 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000395 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000396 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800397 << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
398
399 // Rejects motion events with duplicate pointer ids.
400 pointerProperties[0].id = 1;
401 pointerProperties[1].id = 1;
Garfield Tanfbe732e2020-01-24 11:26:14 -0800402 event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
403 AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
chaviw9eaa22c2020-07-01 16:21:27 -0700404 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -0700405 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
406 ARBITRARY_TIME,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000407 /*pointerCount=*/2, pointerProperties, pointerCoords);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800408 ASSERT_EQ(InputEventInjectionResult::FAILED,
Harry Cutts33476232023-01-30 19:57:29 +0000409 mDispatcher->injectInputEvent(&event, /*targetUid=*/{}, InputEventInjectionSync::NONE,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000410 0ms, 0))
Michael Wrightd02c5b62014-02-10 15:10:22 -0800411 << "Should reject motion events with duplicate pointer ids.";
412}
413
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800414/* Test InputDispatcher for notifyConfigurationChanged and notifySwitch events */
415
416TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
417 constexpr nsecs_t eventTime = 20;
Prabir Pradhan678438e2023-04-13 19:32:51 +0000418 mDispatcher->notifyConfigurationChanged({/*id=*/10, eventTime});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800419 ASSERT_TRUE(mDispatcher->waitForIdle());
420
421 mFakePolicy->assertNotifyConfigurationChangedWasCalled(eventTime);
422}
423
424TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000425 NotifySwitchArgs args(InputEvent::nextId(), /*eventTime=*/20, /*policyFlags=*/0,
426 /*switchValues=*/1,
Harry Cutts33476232023-01-30 19:57:29 +0000427 /*switchMask=*/2);
Prabir Pradhan678438e2023-04-13 19:32:51 +0000428 mDispatcher->notifySwitch(args);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -0800429
430 // InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
431 args.policyFlags |= POLICY_FLAG_TRUSTED;
432 mFakePolicy->assertNotifySwitchWasCalled(args);
433}
434
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700435namespace {
436
Siarhei Vishniakou097c3db2020-05-06 14:18:38 -0700437static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
Siarhei Vishniakou540dbae2020-05-05 18:17:17 -0700438
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000439class FakeMonitorReceiver {
440public:
Linnan Li13bf76a2024-05-05 19:18:02 +0800441 FakeMonitorReceiver(InputDispatcher& dispatcher, const std::string name,
442 ui::LogicalDisplayId displayId)
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700443 : mInputReceiver(*dispatcher.createInputMonitor(displayId, name, MONITOR_PID), name) {}
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000444
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700445 sp<IBinder> getToken() { return mInputReceiver.getToken(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000446
Linnan Li13bf76a2024-05-05 19:18:02 +0800447 void consumeKeyDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700448 mInputReceiver.consumeEvent(InputEventType::KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId,
449 expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000450 }
451
452 std::optional<int32_t> receiveEvent() {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800453 const auto [sequenceNum, _] = mInputReceiver.receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
454 return sequenceNum;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000455 }
456
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700457 void finishEvent(uint32_t consumeSeq) { return mInputReceiver.finishEvent(consumeSeq); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000458
Linnan Li13bf76a2024-05-05 19:18:02 +0800459 void consumeMotionDown(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700460 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_DOWN,
461 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000462 }
463
Linnan Li13bf76a2024-05-05 19:18:02 +0800464 void consumeMotionMove(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700465 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_MOVE,
466 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000467 }
468
Linnan Li13bf76a2024-05-05 19:18:02 +0800469 void consumeMotionUp(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700470 mInputReceiver.consumeEvent(InputEventType::MOTION, AMOTION_EVENT_ACTION_UP,
471 expectedDisplayId, expectedFlags);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000472 }
473
Linnan Li13bf76a2024-05-05 19:18:02 +0800474 void consumeMotionCancel(ui::LogicalDisplayId expectedDisplayId, int32_t expectedFlags = 0) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700475 mInputReceiver.consumeMotionEvent(
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000476 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
477 WithDisplayId(expectedDisplayId),
478 WithFlags(expectedFlags | AMOTION_EVENT_FLAG_CANCELED)));
479 }
480
481 void consumeMotionPointerDown(int32_t pointerIdx) {
482 int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
483 (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700484 mInputReceiver.consumeEvent(InputEventType::MOTION, action, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700485 /*expectedFlags=*/0);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000486 }
487
488 void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) {
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700489 mInputReceiver.consumeMotionEvent(matcher);
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000490 }
491
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -0800492 std::unique_ptr<MotionEvent> consumeMotion() { return mInputReceiver.consumeMotion(); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000493
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -0800494 void assertNoEvents() { mInputReceiver.assertNoEvents(CONSUME_TIMEOUT_NO_EVENT_EXPECTED); }
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000495
496private:
Siarhei Vishniakou2defec02023-06-08 17:24:44 -0700497 FakeInputReceiver mInputReceiver;
Prabir Pradhan112b1ad2023-09-21 09:53:53 +0000498};
499
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800500static InputEventInjectionResult injectKey(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700501 InputDispatcher& dispatcher, int32_t action, int32_t repeatCount,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700502 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800503 InputEventInjectionSync syncMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800504 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000505 bool allowKeyRepeat = true, std::optional<gui::Uid> targetUid = {},
Prabir Pradhan5735a322022-04-11 17:23:34 +0000506 uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Arthur Hungb92218b2018-08-14 12:00:21 +0800507 KeyEvent event;
508 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
509
510 // Define a valid key down event.
Garfield Tanfbe732e2020-01-24 11:26:14 -0800511 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
Harry Cutts33476232023-01-30 19:57:29 +0000512 INVALID_HMAC, action, /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, repeatCount,
513 currentTime, currentTime);
Arthur Hungb92218b2018-08-14 12:00:21 +0800514
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800515 if (!allowKeyRepeat) {
516 policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
517 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800518 // Inject event until dispatch out.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700519 return dispatcher.injectInputEvent(&event, targetUid, syncMode, injectionTimeout, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800520}
521
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700522static void assertInjectedKeyTimesOut(InputDispatcher& dispatcher) {
523 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700524 injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
525 ui::LogicalDisplayId::INVALID, InputEventInjectionSync::WAIT_FOR_RESULT,
526 CONSUME_TIMEOUT_NO_EVENT_EXPECTED);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700527 if (result != InputEventInjectionResult::TIMED_OUT) {
528 FAIL() << "Injection should have timed out, but got " << ftl::enum_string(result);
529 }
530}
531
Linnan Li13bf76a2024-05-05 19:18:02 +0800532static InputEventInjectionResult injectKeyDown(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700533 InputDispatcher& dispatcher,
534 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000535 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700536}
537
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800538// Inject a down event that has key repeat disabled. This allows InputDispatcher to idle without
539// sending a subsequent key up. When key repeat is enabled, the dispatcher cannot idle because it
540// has to be woken up to process the repeating key.
Linnan Li13bf76a2024-05-05 19:18:02 +0800541static InputEventInjectionResult injectKeyDownNoRepeat(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700542 InputDispatcher& dispatcher,
543 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000544 return injectKey(dispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0, displayId,
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800545 InputEventInjectionSync::WAIT_FOR_RESULT, INJECT_EVENT_TIMEOUT,
Harry Cutts33476232023-01-30 19:57:29 +0000546 /*allowKeyRepeat=*/false);
Prabir Pradhan93f342c2021-03-11 15:05:30 -0800547}
548
Linnan Li13bf76a2024-05-05 19:18:02 +0800549static InputEventInjectionResult injectKeyUp(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700550 InputDispatcher& dispatcher,
551 ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Harry Cutts33476232023-01-30 19:57:29 +0000552 return injectKey(dispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0, displayId);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700553}
554
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800555static InputEventInjectionResult injectMotionEvent(
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700556 InputDispatcher& dispatcher, const MotionEvent& event,
Garfield Tandf26e862020-07-01 20:18:19 -0700557 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000558 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000559 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700560 return dispatcher.injectInputEvent(&event, targetUid, injectionMode, injectionTimeout,
561 policyFlags);
Garfield Tandf26e862020-07-01 20:18:19 -0700562}
563
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800564static InputEventInjectionResult injectMotionEvent(
Linnan Li13bf76a2024-05-05 19:18:02 +0800565 InputDispatcher& dispatcher, int32_t action, int32_t source, ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700566 const PointF& position = {100, 200},
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700567 const PointF& cursorPosition = {AMOTION_EVENT_INVALID_CURSOR_POSITION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -0700568 AMOTION_EVENT_INVALID_CURSOR_POSITION},
569 std::chrono::milliseconds injectionTimeout = INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800570 InputEventInjectionSync injectionMode = InputEventInjectionSync::WAIT_FOR_RESULT,
Prabir Pradhan5735a322022-04-11 17:23:34 +0000571 nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC),
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +0000572 std::optional<gui::Uid> targetUid = {}, uint32_t policyFlags = DEFAULT_POLICY_FLAGS) {
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700573 MotionEventBuilder motionBuilder =
574 MotionEventBuilder(action, source)
575 .displayId(displayId)
576 .eventTime(eventTime)
577 .rawXCursorPosition(cursorPosition.x)
578 .rawYCursorPosition(cursorPosition.y)
579 .pointer(
580 PointerBuilder(/*id=*/0, ToolType::FINGER).x(position.x).y(position.y));
581 if (MotionEvent::getActionMasked(action) == ACTION_DOWN) {
582 motionBuilder.downTime(eventTime);
583 }
Arthur Hungb92218b2018-08-14 12:00:21 +0800584
585 // Inject event until dispatch out.
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -0700586 return injectMotionEvent(dispatcher, motionBuilder.build(), injectionTimeout, injectionMode,
587 targetUid, policyFlags);
Arthur Hungb92218b2018-08-14 12:00:21 +0800588}
589
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700590static InputEventInjectionResult injectMotionDown(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800591 ui::LogicalDisplayId displayId,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700592 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700593 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location);
Garfield Tan00f511d2019-06-12 16:55:40 -0700594}
595
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700596static InputEventInjectionResult injectMotionUp(InputDispatcher& dispatcher, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800597 ui::LogicalDisplayId displayId,
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800598 const PointF& location = {100, 200}) {
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -0700599 return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location);
Michael Wright3a240c42019-12-10 20:53:41 +0000600}
601
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700602static NotifyKeyArgs generateKeyArgs(
603 int32_t action, ui::LogicalDisplayId displayId = ui::LogicalDisplayId::INVALID) {
Jackal Guof9696682018-10-05 12:23:23 +0800604 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
605 // Define a valid key event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000606 NotifyKeyArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID,
607 AINPUT_SOURCE_KEYBOARD, displayId, POLICY_FLAG_PASS_TO_USER, action,
608 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
Jackal Guof9696682018-10-05 12:23:23 +0800609
610 return args;
611}
612
Prabir Pradhan678438e2023-04-13 19:32:51 +0000613[[nodiscard]] static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
Linnan Li13bf76a2024-05-05 19:18:02 +0800614 ui::LogicalDisplayId displayId,
Prabir Pradhan678438e2023-04-13 19:32:51 +0000615 const std::vector<PointF>& points) {
chaviwd1c23182019-12-20 18:44:56 -0800616 size_t pointerCount = points.size();
chaviwaf87b3e2019-10-01 16:59:28 -0700617 if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) {
618 EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer";
619 }
620
chaviwd1c23182019-12-20 18:44:56 -0800621 PointerProperties pointerProperties[pointerCount];
622 PointerCoords pointerCoords[pointerCount];
Jackal Guof9696682018-10-05 12:23:23 +0800623
chaviwd1c23182019-12-20 18:44:56 -0800624 for (size_t i = 0; i < pointerCount; i++) {
625 pointerProperties[i].clear();
626 pointerProperties[i].id = i;
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -0700627 pointerProperties[i].toolType = ToolType::FINGER;
Jackal Guof9696682018-10-05 12:23:23 +0800628
chaviwd1c23182019-12-20 18:44:56 -0800629 pointerCoords[i].clear();
630 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, points[i].x);
631 pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, points[i].y);
632 }
Jackal Guof9696682018-10-05 12:23:23 +0800633
634 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
635 // Define a valid motion event.
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000636 NotifyMotionArgs args(InputEvent::nextId(), currentTime, /*readTime=*/0, DEVICE_ID, source,
637 displayId, POLICY_FLAG_PASS_TO_USER, action, /*actionButton=*/0,
638 /*flags=*/0, AMETA_NONE, /*buttonState=*/0, MotionClassification::NONE,
chaviwd1c23182019-12-20 18:44:56 -0800639 AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000640 pointerCoords, /*xPrecision=*/0, /*yPrecision=*/0,
Garfield Tan00f511d2019-06-12 16:55:40 -0700641 AMOTION_EVENT_INVALID_CURSOR_POSITION,
Harry Cutts101ee9b2023-07-06 18:04:14 +0000642 AMOTION_EVENT_INVALID_CURSOR_POSITION, currentTime, /*videoFrames=*/{});
Jackal Guof9696682018-10-05 12:23:23 +0800643
644 return args;
645}
646
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -0800647static NotifyMotionArgs generateTouchArgs(int32_t action, const std::vector<PointF>& points) {
648 return generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, points);
649}
650
Linnan Li13bf76a2024-05-05 19:18:02 +0800651static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source,
652 ui::LogicalDisplayId displayId) {
chaviwd1c23182019-12-20 18:44:56 -0800653 return generateMotionArgs(action, source, displayId, {PointF{100, 200}});
654}
655
Prabir Pradhan5cc1a692021-08-06 14:01:18 +0000656static NotifyPointerCaptureChangedArgs generatePointerCaptureChangedArgs(
657 const PointerCaptureRequest& request) {
Prabir Pradhana8fe7c52023-12-14 22:07:23 +0000658 return NotifyPointerCaptureChangedArgs(InputEvent::nextId(), systemTime(SYSTEM_TIME_MONOTONIC),
659 request);
Prabir Pradhan99987712020-11-10 18:43:05 -0800660}
661
Siarhei Vishniakouadeb6fa2023-05-26 09:11:06 -0700662} // namespace
663
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800664/**
665 * When a window unexpectedly disposes of its input channel, policy should be notified about the
666 * broken channel.
667 */
668TEST_F(InputDispatcherTest, WhenInputChannelBreaks_PolicyIsNotified) {
669 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700670 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher,
671 "Window that breaks its input channel",
672 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800673
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700674 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7aa3e942021-11-18 09:49:11 -0800675
676 // Window closes its channel, but the window remains.
677 window->destroyReceiver();
678 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(window->getInfo()->token);
679}
680
Arthur Hungb92218b2018-08-14 12:00:21 +0800681TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700682 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700683 sp<FakeWindowHandle> window =
684 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
685 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800686
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700687 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700689 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
690 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800691 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800692
693 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700694 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800695}
696
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800697using InputDispatcherDeathTest = InputDispatcherTest;
698
699/**
700 * When 'onWindowInfosChanged' arguments contain a duplicate entry for the same window, dispatcher
701 * should crash.
702 */
703TEST_F(InputDispatcherDeathTest, DuplicateWindowInfosAbortDispatcher) {
704 testing::GTEST_FLAG(death_test_style) = "threadsafe";
705 ScopedSilentDeath _silentDeath;
706
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);
Siarhei Vishniakouaeed0da2024-01-09 08:57:13 -0800711 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
712 {{*window->getInfo(), *window->getInfo()}, {}, 0, 0}),
713 "Incorrect WindowInfosUpdate provided");
714}
715
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700716TEST_F(InputDispatcherTest, WhenDisplayNotSpecified_InjectMotionToDefaultDisplay) {
717 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700718 sp<FakeWindowHandle> window =
719 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
720 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700721
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700722 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700723 // Inject a MotionEvent to an unknown display.
724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700725 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
726 ui::LogicalDisplayId::INVALID))
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700727 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
728
729 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700730 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -0700731}
732
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700733/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700734 * Calling onWindowInfosChanged once should not cause any issues.
735 * This test serves as a sanity check for the next test, where onWindowInfosChanged is
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700736 * called twice.
737 */
Prabir Pradhan76bdecb2022-01-31 11:14:15 -0800738TEST_F(InputDispatcherTest, SetInputWindowOnceWithSingleTouchWindow) {
Chris Yea209fde2020-07-22 13:54:51 -0700739 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700740 sp<FakeWindowHandle> window =
741 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
742 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700743 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700744
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700745 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700747 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
748 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800749 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700750
751 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700752 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700753}
754
755/**
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700756 * Calling onWindowInfosChanged twice, with the same info, should not cause any issues.
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700757 */
758TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700759 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700760 sp<FakeWindowHandle> window =
761 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
762 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700763 window->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700764
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700765 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
766 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700768 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
769 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800770 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700771
772 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700773 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -0700774}
775
Arthur Hungb92218b2018-08-14 12:00:21 +0800776// The foreground window should receive the first touch down event.
777TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
Chris Yea209fde2020-07-22 13:54:51 -0700778 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700779 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
780 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -1000781 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700782 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
783 ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800784
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700785 mDispatcher->onWindowInfosChanged(
786 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700788 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
789 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -0800790 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +0800791
792 // Top window should receive the touch down event. Second window should not receive anything.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700793 windowTop->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +0800794 windowSecond->assertNoEvents();
795}
796
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000797/**
798 * Two windows: A top window, and a wallpaper behind the window.
799 * Touch goes to the top window, and then top window disappears. Ensure that wallpaper window
800 * gets ACTION_CANCEL.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800801 * 1. foregroundWindow <-- dup touch to wallpaper
802 * 2. wallpaperWindow <-- is wallpaper
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000803 */
804TEST_F(InputDispatcherTest, WhenForegroundWindowDisappears_WallpaperTouchIsCanceled) {
805 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
806 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700807 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
808 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800809 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000810 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700811 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
812 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800813 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000814
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700815 mDispatcher->onWindowInfosChanged(
816 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800818 injectMotionEvent(*mDispatcher,
819 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
820 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(200))
821 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000822 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
823
824 // Both foreground window and its wallpaper should receive the touch down
825 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700826 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000827
828 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800829 injectMotionEvent(*mDispatcher,
830 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
831 .pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(200))
832 .build()))
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000833 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
834
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -0800835 foregroundWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700836 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000837
838 // Now the foreground window goes away, but the wallpaper stays
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700839 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000840 foregroundWindow->consumeMotionCancel();
841 // Since the "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700842 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +0000843}
844
845/**
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800846 * Two fingers down on the window, and lift off the first finger.
847 * Next, cancel the gesture to the window by removing the window. Make sure that the CANCEL event
848 * contains a single pointer.
849 */
850TEST_F(InputDispatcherTest, CancelAfterPointer0Up) {
851 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700852 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
853 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800854
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700855 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800856 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +0000857 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
858 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
859 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800860 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000861 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
862 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
863 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
864 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800865 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +0000866 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
867 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
868 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(100))
869 .build());
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800870 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
871 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
872 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
873
874 // Remove the window. The gesture should be canceled
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700875 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -0800876 const std::map<int32_t, PointF> expectedPointers{{1, PointF{110, 100}}};
877 window->consumeMotionEvent(
878 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedPointers)));
879}
880
881/**
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800882 * Same test as WhenForegroundWindowDisappears_WallpaperTouchIsCanceled above,
883 * with the following differences:
884 * After ACTION_DOWN, Wallpaper window hangs up its channel, which forces the dispatcher to
885 * clean up the connection.
886 * This later may crash dispatcher during ACTION_CANCEL synthesis, if the dispatcher is not careful.
887 * Ensure that there's no crash in the dispatcher.
888 */
889TEST_F(InputDispatcherTest, WhenWallpaperDisappears_NoCrash) {
890 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
891 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700892 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
893 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800894 foregroundWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800895 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700896 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
897 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -0800898 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800899
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700900 mDispatcher->onWindowInfosChanged(
901 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800902 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700903 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
904 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800905 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
906
907 // Both foreground window and its wallpaper should receive the touch down
908 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700909 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800910
911 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -0700912 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700913 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800914 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
915
916 foregroundWindow->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700917 wallpaperWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800918
919 // Wallpaper closes its channel, but the window remains.
920 wallpaperWindow->destroyReceiver();
921 mFakePolicy->assertNotifyInputChannelBrokenWasCalled(wallpaperWindow->getInfo()->token);
922
923 // Now the foreground window goes away, but the wallpaper stays, even though its channel
924 // is no longer valid.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -0700925 mDispatcher->onWindowInfosChanged({{*wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2b030972021-11-18 10:01:27 -0800926 foregroundWindow->consumeMotionCancel();
927}
928
Linnan Li72352222024-04-12 18:55:57 +0800929/**
930 * Two windows: left and right, and a separate wallpaper window underneath each. Device A sends a
931 * down event to the left window. Device B sends a down event to the right window. Next, the right
932 * window disappears. Both the right window and its wallpaper window should receive cancel event.
933 * The left window and its wallpaper window should not receive any events.
934 */
935TEST_F(InputDispatcherTest, MultiDeviceDisappearingWindowWithWallpaperWindows) {
936 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
937 sp<FakeWindowHandle> leftForegroundWindow =
938 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700939 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800940 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
941 leftForegroundWindow->setDupTouchToWallpaper(true);
942 sp<FakeWindowHandle> leftWallpaperWindow =
943 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700944 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800945 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
946 leftWallpaperWindow->setIsWallpaper(true);
947
948 sp<FakeWindowHandle> rightForegroundWindow =
949 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700950 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800951 rightForegroundWindow->setFrame(Rect(100, 0, 200, 100));
952 rightForegroundWindow->setDupTouchToWallpaper(true);
953 sp<FakeWindowHandle> rightWallpaperWindow =
954 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -0700955 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +0800956 rightWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
957 rightWallpaperWindow->setIsWallpaper(true);
958
959 mDispatcher->onWindowInfosChanged(
960 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
961 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
962 {},
963 0,
964 0});
965
966 const DeviceId deviceA = 9;
967 const DeviceId deviceB = 3;
968 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
969 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
970 .deviceId(deviceA)
971 .build());
972 leftForegroundWindow->consumeMotionEvent(
973 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
974 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
975 WithDeviceId(deviceA),
976 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
977
978 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
979 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
980 .deviceId(deviceB)
981 .build());
982 rightForegroundWindow->consumeMotionEvent(
983 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
984 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
985 WithDeviceId(deviceB),
986 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
987
988 // Now right foreground window disappears, but right wallpaper window remains.
989 mDispatcher->onWindowInfosChanged(
990 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
991 *rightWallpaperWindow->getInfo()},
992 {},
993 0,
994 0});
995
996 // Left foreground window and left wallpaper window still exist, and should not receive any
997 // events.
998 leftForegroundWindow->assertNoEvents();
999 leftWallpaperWindow->assertNoEvents();
1000 // Since right foreground window disappeared, right wallpaper window and right foreground window
1001 // should receive cancel events.
1002 rightForegroundWindow->consumeMotionEvent(
1003 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1004 rightWallpaperWindow->consumeMotionEvent(
1005 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1006 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1007}
1008
1009/**
1010 * Three windows arranged horizontally and without any overlap. Every window has a
1011 * wallpaper window underneath. The middle window also has SLIPPERY flag.
1012 * Device A sends a down event to the left window. Device B sends a down event to the middle window.
1013 * Next, device B sends move event to the right window. Touch for device B should slip from the
1014 * middle window to the right window. Also, the right wallpaper window should receive a down event.
1015 * The middle window and its wallpaper window should receive a cancel event. The left window should
1016 * not receive any events. If device B continues to report events, the right window and its
1017 * wallpaper window should receive remaining events.
1018 */
1019TEST_F(InputDispatcherTest, MultiDeviceSlipperyTouchWithWallpaperWindow) {
1020 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1021 sp<FakeWindowHandle> leftForegroundWindow =
1022 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001023 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001024 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1025 leftForegroundWindow->setDupTouchToWallpaper(true);
1026 sp<FakeWindowHandle> leftWallpaperWindow =
1027 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001028 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001029 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1030 leftWallpaperWindow->setIsWallpaper(true);
1031
1032 sp<FakeWindowHandle> middleForegroundWindow =
1033 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001034 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001035 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1036 middleForegroundWindow->setDupTouchToWallpaper(true);
1037 middleForegroundWindow->setSlippery(true);
1038 sp<FakeWindowHandle> middleWallpaperWindow =
1039 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001040 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001041 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1042 middleWallpaperWindow->setIsWallpaper(true);
1043
1044 sp<FakeWindowHandle> rightForegroundWindow =
1045 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001046 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001047 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1048 rightForegroundWindow->setDupTouchToWallpaper(true);
1049 sp<FakeWindowHandle> rightWallpaperWindow =
1050 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001051 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001052 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1053 rightWallpaperWindow->setIsWallpaper(true);
1054
1055 mDispatcher->onWindowInfosChanged(
1056 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1057 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1058 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1059 {},
1060 0,
1061 0});
1062
1063 const DeviceId deviceA = 9;
1064 const DeviceId deviceB = 3;
1065 // Device A sends a DOWN event to the left window
1066 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1067 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1068 .deviceId(deviceA)
1069 .build());
1070 leftForegroundWindow->consumeMotionEvent(
1071 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1072 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1073 WithDeviceId(deviceA),
1074 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1075 // Device B sends a DOWN event to the middle window
1076 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1077 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1078 .deviceId(deviceB)
1079 .build());
1080 middleForegroundWindow->consumeMotionEvent(
1081 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1082 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1083 WithDeviceId(deviceB),
1084 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1085 // Move the events of device B to the top of the right window.
1086 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1087 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
1088 .deviceId(deviceB)
1089 .build());
1090 middleForegroundWindow->consumeMotionEvent(
1091 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1092 middleWallpaperWindow->consumeMotionEvent(
1093 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1094 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1095 rightForegroundWindow->consumeMotionEvent(
1096 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1097 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1098 WithDeviceId(deviceB),
1099 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1100 // Make sure the window on the right can receive the remaining events.
1101 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1102 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1103 .deviceId(deviceB)
1104 .build());
1105 leftForegroundWindow->assertNoEvents();
1106 leftWallpaperWindow->assertNoEvents();
1107 middleForegroundWindow->assertNoEvents();
1108 middleWallpaperWindow->assertNoEvents();
1109 rightForegroundWindow->consumeMotionEvent(
1110 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
1111 rightWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1112 WithDeviceId(deviceB),
1113 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1114}
1115
1116/**
1117 * Similar to the test above, we have three windows, they are arranged horizontally and without any
1118 * overlap, and every window has a wallpaper window. The middle window is a simple window, without
1119 * any special flags. Device A reports a down event that lands in left window. Device B sends a down
1120 * event to the middle window and then touch is transferred from the middle window to the right
1121 * window. The right window and its wallpaper window should receive a down event. The middle window
1122 * and its wallpaper window should receive a cancel event. The left window should not receive any
1123 * events. Subsequent events reported by device B should go to the right window and its wallpaper.
1124 */
1125TEST_F(InputDispatcherTest, MultiDeviceTouchTransferWithWallpaperWindows) {
1126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1127 sp<FakeWindowHandle> leftForegroundWindow =
1128 sp<FakeWindowHandle>::make(application, mDispatcher, "Left foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001129 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001130 leftForegroundWindow->setFrame(Rect(0, 0, 100, 100));
1131 leftForegroundWindow->setDupTouchToWallpaper(true);
1132 sp<FakeWindowHandle> leftWallpaperWindow =
1133 sp<FakeWindowHandle>::make(application, mDispatcher, "Left wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001134 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001135 leftWallpaperWindow->setFrame(Rect(0, 0, 100, 100));
1136 leftWallpaperWindow->setIsWallpaper(true);
1137
1138 sp<FakeWindowHandle> middleForegroundWindow =
1139 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001140 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001141 middleForegroundWindow->setFrame(Rect(100, 0, 200, 100));
1142 middleForegroundWindow->setDupTouchToWallpaper(true);
1143 sp<FakeWindowHandle> middleWallpaperWindow =
1144 sp<FakeWindowHandle>::make(application, mDispatcher, "Middle wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001145 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001146 middleWallpaperWindow->setFrame(Rect(100, 0, 200, 100));
1147 middleWallpaperWindow->setIsWallpaper(true);
1148
1149 sp<FakeWindowHandle> rightForegroundWindow =
1150 sp<FakeWindowHandle>::make(application, mDispatcher, "Right foreground window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001151 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001152 rightForegroundWindow->setFrame(Rect(200, 0, 300, 100));
1153 rightForegroundWindow->setDupTouchToWallpaper(true);
1154 sp<FakeWindowHandle> rightWallpaperWindow =
1155 sp<FakeWindowHandle>::make(application, mDispatcher, "Right wallpaper window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001156 ui::LogicalDisplayId::DEFAULT);
Linnan Li72352222024-04-12 18:55:57 +08001157 rightWallpaperWindow->setFrame(Rect(200, 0, 300, 100));
1158 rightWallpaperWindow->setIsWallpaper(true);
1159
1160 mDispatcher->onWindowInfosChanged(
1161 {{*leftForegroundWindow->getInfo(), *leftWallpaperWindow->getInfo(),
1162 *middleForegroundWindow->getInfo(), *middleWallpaperWindow->getInfo(),
1163 *rightForegroundWindow->getInfo(), *rightWallpaperWindow->getInfo()},
1164 {},
1165 0,
1166 0});
1167
1168 const DeviceId deviceA = 9;
1169 const DeviceId deviceB = 3;
1170 // Device A touch down on the left window
1171 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1172 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
1173 .deviceId(deviceA)
1174 .build());
1175 leftForegroundWindow->consumeMotionEvent(
1176 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
1177 leftWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1178 WithDeviceId(deviceA),
1179 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1180 // Device B touch down on the middle window
1181 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1182 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
1183 .deviceId(deviceB)
1184 .build());
1185 middleForegroundWindow->consumeMotionEvent(
1186 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
1187 middleWallpaperWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1188 WithDeviceId(deviceB),
1189 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
1190
1191 // Transfer touch from the middle window to the right window.
1192 ASSERT_TRUE(mDispatcher->transferTouchGesture(middleForegroundWindow->getToken(),
1193 rightForegroundWindow->getToken()));
1194
1195 middleForegroundWindow->consumeMotionEvent(
1196 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
1197 middleWallpaperWindow->consumeMotionEvent(
1198 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB),
1199 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_CANCELED)));
1200 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN),
1201 WithDeviceId(deviceB),
1202 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1203 rightWallpaperWindow->consumeMotionEvent(
1204 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
1205 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1206
1207 // Make sure the right window can receive the remaining events.
1208 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1209 .pointer(PointerBuilder(0, ToolType::FINGER).x(251).y(51))
1210 .deviceId(deviceB)
1211 .build());
1212 leftForegroundWindow->assertNoEvents();
1213 leftWallpaperWindow->assertNoEvents();
1214 middleForegroundWindow->assertNoEvents();
1215 middleWallpaperWindow->assertNoEvents();
1216 rightForegroundWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE),
1217 WithDeviceId(deviceB),
1218 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1219 rightWallpaperWindow->consumeMotionEvent(
1220 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB),
1221 WithFlags(EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
1222}
1223
Arthur Hungc539dbb2022-12-08 07:45:36 +00001224class ShouldSplitTouchFixture : public InputDispatcherTest,
1225 public ::testing::WithParamInterface<bool> {};
1226INSTANTIATE_TEST_SUITE_P(InputDispatcherTest, ShouldSplitTouchFixture,
1227 ::testing::Values(true, false));
Siarhei Vishniakou2b030972021-11-18 10:01:27 -08001228/**
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001229 * A single window that receives touch (on top), and a wallpaper window underneath it.
1230 * The top window gets a multitouch gesture.
1231 * Ensure that wallpaper gets the same gesture.
1232 */
Arthur Hungc539dbb2022-12-08 07:45:36 +00001233TEST_P(ShouldSplitTouchFixture, WallpaperWindowReceivesMultiTouch) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001234 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Arthur Hungc539dbb2022-12-08 07:45:36 +00001235 sp<FakeWindowHandle> foregroundWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001236 sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
1237 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001238 foregroundWindow->setDupTouchToWallpaper(true);
1239 foregroundWindow->setPreventSplitting(GetParam());
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001240
1241 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001242 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1243 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001244 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001245
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001246 mDispatcher->onWindowInfosChanged(
1247 {{*foregroundWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001248
1249 // Touch down on top window
1250 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001251 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1252 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001253 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1254
1255 // Both top window and its wallpaper should receive the touch down
Arthur Hungc539dbb2022-12-08 07:45:36 +00001256 foregroundWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001257 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001258
1259 // Second finger down on the top window
1260 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001261 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001262 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001263 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1264 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001265 .build();
1266 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001267 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001268 InputEventInjectionSync::WAIT_FOR_RESULT))
1269 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +00001270 foregroundWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001271 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001272 EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001273
1274 const MotionEvent secondFingerUpEvent =
1275 MotionEventBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001276 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hungc539dbb2022-12-08 07:45:36 +00001277 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001278 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1279 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001280 .build();
1281 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001282 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hungc539dbb2022-12-08 07:45:36 +00001283 InputEventInjectionSync::WAIT_FOR_RESULT))
1284 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1285 foregroundWindow->consumeMotionPointerUp(0);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001286 wallpaperWindow->consumeMotionPointerUp(0, ui::LogicalDisplayId::DEFAULT,
1287 EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001288
1289 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001290 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001291 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1292 AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001293 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001294 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001295 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001296 .x(100)
1297 .y(100))
1298 .build(),
1299 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001300 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001301 foregroundWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
1302 wallpaperWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001303}
1304
1305/**
1306 * Two windows: a window on the left and window on the right.
1307 * A third window, wallpaper, is behind both windows, and spans both top windows.
1308 * The first touch down goes to the left window. A second pointer touches down on the right window.
1309 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1310 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1311 * ACTION_POINTER_DOWN(1).
1312 */
1313TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1314 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001315 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1316 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001317 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001318 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001319
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001320 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1321 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001322 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001323 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001324
1325 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001326 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1327 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001328 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001329 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001330
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001331 mDispatcher->onWindowInfosChanged(
1332 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1333 {},
1334 0,
1335 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001336
1337 // Touch down on left window
1338 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001339 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1340 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001341 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1342
1343 // Both foreground window and its wallpaper should receive the touch down
1344 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001345 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001346
1347 // Second finger down on the right window
1348 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001349 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001350 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001351 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1352 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001353 .build();
1354 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001355 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001356 InputEventInjectionSync::WAIT_FOR_RESULT))
1357 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1358
1359 leftWindow->consumeMotionMove();
1360 // Since the touch is split, right window gets ACTION_DOWN
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001361 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1362 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001363 EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001364
1365 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001366 mDispatcher->onWindowInfosChanged(
1367 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001368 leftWindow->consumeMotionCancel();
1369 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001370 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001371
1372 // The pointer that's still down on the right window moves, and goes to the right window only.
1373 // As far as the dispatcher's concerned though, both pointers are still present.
1374 const MotionEvent secondFingerMoveEvent =
1375 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1376 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001377 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1378 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001379 .build();
1380 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001381 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001382 InputEventInjectionSync::WAIT_FOR_RESULT));
1383 rightWindow->consumeMotionMove();
1384
1385 leftWindow->assertNoEvents();
1386 rightWindow->assertNoEvents();
1387 wallpaperWindow->assertNoEvents();
1388}
1389
Arthur Hungc539dbb2022-12-08 07:45:36 +00001390/**
1391 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
1392 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
1393 * The right window should receive ACTION_DOWN.
1394 */
1395TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00001396 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001397 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1398 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001399 leftWindow->setFrame(Rect(0, 0, 200, 200));
1400 leftWindow->setDupTouchToWallpaper(true);
1401 leftWindow->setSlippery(true);
1402
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001403 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1404 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001405 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00001406
1407 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001408 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1409 ui::LogicalDisplayId::DEFAULT);
Arthur Hung74c248d2022-11-23 07:09:59 +00001410 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00001411
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001412 mDispatcher->onWindowInfosChanged(
1413 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1414 {},
1415 0,
1416 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00001417
Arthur Hungc539dbb2022-12-08 07:45:36 +00001418 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00001419 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001420 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1421 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001422 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00001423
1424 // Both foreground window and its wallpaper should receive the touch down
1425 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001426 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001427
Arthur Hungc539dbb2022-12-08 07:45:36 +00001428 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00001429 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001430 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001431 ui::LogicalDisplayId::DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001432 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1433
Arthur Hungc539dbb2022-12-08 07:45:36 +00001434 leftWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001435 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1436 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001437}
1438
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001439/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001440 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1441 * interactive, it might stop sending this flag.
1442 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
1443 * to have a consistent input stream.
1444 *
1445 * Test procedure:
1446 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
1447 * DOWN (new gesture).
1448 *
1449 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
1450 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
1451 *
1452 * We technically just need a single window here, but we are using two windows (spy on top and a
1453 * regular window below) to emulate the actual situation where it happens on the device.
1454 */
1455TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
1456 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001457 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
1458 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001459 spyWindow->setFrame(Rect(0, 0, 200, 200));
1460 spyWindow->setTrustedOverlay(true);
1461 spyWindow->setSpy(true);
1462
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001463 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1464 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001465 window->setFrame(Rect(0, 0, 200, 200));
1466
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001467 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001468 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001469
1470 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001471 mDispatcher->notifyMotion(
1472 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1473 .deviceId(touchDeviceId)
1474 .policyFlags(DEFAULT_POLICY_FLAGS)
1475 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1476 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001477
Prabir Pradhan678438e2023-04-13 19:32:51 +00001478 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1479 .deviceId(touchDeviceId)
1480 .policyFlags(DEFAULT_POLICY_FLAGS)
1481 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1482 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1483 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001484 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1485 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1486 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1487 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1488
1489 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001490 mDispatcher->notifyMotion(
1491 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
1492 .deviceId(touchDeviceId)
1493 .policyFlags(0)
1494 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1495 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1496 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001497 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1498 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1499
1500 // We don't need to reset the device to reproduce the issue, but the reset event typically
1501 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001502 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001503
1504 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00001505 mDispatcher->notifyMotion(
1506 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1507 .deviceId(touchDeviceId)
1508 .policyFlags(DEFAULT_POLICY_FLAGS)
1509 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1510 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001511 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1512 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1513
1514 // No more events
1515 spyWindow->assertNoEvents();
1516 window->assertNoEvents();
1517}
1518
1519/**
Linnan Li907ae732023-09-05 17:14:21 +08001520 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
1521 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1522 * interactive, it might stop sending this flag.
1523 * We've already ensured the consistency of the touch event in this case, and we should also ensure
1524 * the consistency of the hover event in this case.
1525 *
1526 * Test procedure:
1527 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
1528 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
1529 *
1530 * We expect to receive two full streams of hover events.
1531 */
1532TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
1533 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1534
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001535 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1536 ui::LogicalDisplayId::DEFAULT);
Linnan Li907ae732023-09-05 17:14:21 +08001537 window->setFrame(Rect(0, 0, 300, 300));
1538
1539 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1540
1541 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1542 .policyFlags(DEFAULT_POLICY_FLAGS)
1543 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
1544 .build());
1545 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1546
1547 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1548 .policyFlags(DEFAULT_POLICY_FLAGS)
1549 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1550 .build());
1551 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1552
1553 // Send hover exit without the default policy flags.
1554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1555 .policyFlags(0)
1556 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1557 .build());
1558
1559 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1560
1561 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
1562 // right event.
1563 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1564 .policyFlags(DEFAULT_POLICY_FLAGS)
1565 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
1566 .build());
1567 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1568
1569 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1570 .policyFlags(DEFAULT_POLICY_FLAGS)
1571 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1572 .build());
1573 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1574
1575 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1576 .policyFlags(DEFAULT_POLICY_FLAGS)
1577 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1578 .build());
1579 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1580}
1581
1582/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001583 * Two windows: a window on the left and a window on the right.
1584 * Mouse is hovered from the right window into the left window.
1585 * Next, we tap on the left window, where the cursor was last seen.
1586 * The second tap is done onto the right window.
1587 * The mouse and tap are from two different devices.
1588 * We technically don't need to set the downtime / eventtime for these events, but setting these
1589 * explicitly helps during debugging.
1590 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1591 * In the buggy implementation, a tap on the right window would cause a crash.
1592 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001593TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap_legacy) {
1594 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
1595
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001596 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001597 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1598 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001599 leftWindow->setFrame(Rect(0, 0, 200, 200));
1600
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001601 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1602 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001603 rightWindow->setFrame(Rect(200, 0, 400, 200));
1604
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001605 mDispatcher->onWindowInfosChanged(
1606 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001607 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1608 // stale.
1609 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1610 const int32_t mouseDeviceId = 6;
1611 const int32_t touchDeviceId = 4;
1612 // Move the cursor from right
1613 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001614 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001615 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1616 AINPUT_SOURCE_MOUSE)
1617 .deviceId(mouseDeviceId)
1618 .downTime(baseTime + 10)
1619 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001620 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001621 .build()));
1622 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1623
1624 // .. to the left window
1625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001626 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001627 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1628 AINPUT_SOURCE_MOUSE)
1629 .deviceId(mouseDeviceId)
1630 .downTime(baseTime + 10)
1631 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001632 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001633 .build()));
1634 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1635 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1636 // Now tap the left window
1637 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001638 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001639 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1640 AINPUT_SOURCE_TOUCHSCREEN)
1641 .deviceId(touchDeviceId)
1642 .downTime(baseTime + 40)
1643 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001644 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001645 .build()));
1646 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1647 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1648
1649 // release tap
1650 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001651 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001652 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1653 AINPUT_SOURCE_TOUCHSCREEN)
1654 .deviceId(touchDeviceId)
1655 .downTime(baseTime + 40)
1656 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001657 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001658 .build()));
1659 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1660
1661 // Tap the window on the right
1662 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001663 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001664 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1665 AINPUT_SOURCE_TOUCHSCREEN)
1666 .deviceId(touchDeviceId)
1667 .downTime(baseTime + 60)
1668 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001669 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001670 .build()));
1671 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1672
1673 // release tap
1674 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001675 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001676 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1677 AINPUT_SOURCE_TOUCHSCREEN)
1678 .deviceId(touchDeviceId)
1679 .downTime(baseTime + 60)
1680 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001681 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001682 .build()));
1683 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1684
1685 // No more events
1686 leftWindow->assertNoEvents();
1687 rightWindow->assertNoEvents();
1688}
1689
1690/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001691 * Two windows: a window on the left and a window on the right.
1692 * Mouse is hovered from the right window into the left window.
1693 * Next, we tap on the left window, where the cursor was last seen.
1694 * The second tap is done onto the right window.
1695 * The mouse and tap are from two different devices.
1696 * We technically don't need to set the downtime / eventtime for these events, but setting these
1697 * explicitly helps during debugging.
1698 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1699 * In the buggy implementation, a tap on the right window would cause a crash.
1700 */
1701TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
1702 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1703
1704 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001705 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1706 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001707 leftWindow->setFrame(Rect(0, 0, 200, 200));
1708
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001709 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1710 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001711 rightWindow->setFrame(Rect(200, 0, 400, 200));
1712
1713 mDispatcher->onWindowInfosChanged(
1714 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
1715 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1716 // stale.
1717 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1718 const int32_t mouseDeviceId = 6;
1719 const int32_t touchDeviceId = 4;
1720 // Move the cursor from right
1721 mDispatcher->notifyMotion(
1722 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1723 .deviceId(mouseDeviceId)
1724 .downTime(baseTime + 10)
1725 .eventTime(baseTime + 20)
1726 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
1727 .build());
1728 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1729
1730 // .. to the left window
1731 mDispatcher->notifyMotion(
1732 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1733 .deviceId(mouseDeviceId)
1734 .downTime(baseTime + 10)
1735 .eventTime(baseTime + 30)
1736 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
1737 .build());
1738 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1739 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1740 // Now tap the left window
1741 mDispatcher->notifyMotion(
1742 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1743 .deviceId(touchDeviceId)
1744 .downTime(baseTime + 40)
1745 .eventTime(baseTime + 40)
1746 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1747 .build());
1748 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1749
1750 // release tap
1751 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1752 .deviceId(touchDeviceId)
1753 .downTime(baseTime + 40)
1754 .eventTime(baseTime + 50)
1755 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1756 .build());
1757 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1758
1759 // Tap the window on the right
1760 mDispatcher->notifyMotion(
1761 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1762 .deviceId(touchDeviceId)
1763 .downTime(baseTime + 60)
1764 .eventTime(baseTime + 60)
1765 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1766 .build());
1767 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1768
1769 // release tap
1770 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1771 .deviceId(touchDeviceId)
1772 .downTime(baseTime + 60)
1773 .eventTime(baseTime + 70)
1774 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1775 .build());
1776 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1777
1778 // No more events
1779 leftWindow->assertNoEvents();
1780 rightWindow->assertNoEvents();
1781}
1782
1783/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001784 * Start hovering in a window. While this hover is still active, make another window appear on top.
1785 * The top, obstructing window has no input channel, so it's not supposed to receive input.
1786 * While the top window is present, the hovering is stopped.
1787 * Later, hovering gets resumed again.
1788 * Ensure that new hover gesture is handled correctly.
1789 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
1790 * to the window that's currently being hovered over.
1791 */
1792TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
1793 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001794 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1795 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001796 window->setFrame(Rect(0, 0, 200, 200));
1797
1798 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001799 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001800
1801 // Start hovering in the window
1802 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1803 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1804 .build());
1805 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1806
1807 // Now, an obscuring window appears!
1808 sp<FakeWindowHandle> obscuringWindow =
1809 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001810 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001811 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001812 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1813 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1814 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1815 obscuringWindow->setNoInputChannel(true);
1816 obscuringWindow->setFocusable(false);
1817 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001818 mDispatcher->onWindowInfosChanged(
1819 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001820
1821 // While this new obscuring window is present, the hovering is stopped
1822 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1823 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1824 .build());
1825 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1826
1827 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001828 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001829
1830 // And a new hover gesture starts.
1831 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1832 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1833 .build());
1834 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1835}
1836
1837/**
1838 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
1839 * the obscuring window.
1840 */
1841TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
1842 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001843 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1844 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001845 window->setFrame(Rect(0, 0, 200, 200));
1846
1847 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001848 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001849
1850 // Start hovering in the window
1851 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1852 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1853 .build());
1854 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1855
1856 // Now, an obscuring window appears!
1857 sp<FakeWindowHandle> obscuringWindow =
1858 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001859 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001860 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001861 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1862 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1863 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1864 obscuringWindow->setNoInputChannel(true);
1865 obscuringWindow->setFocusable(false);
1866 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001867 mDispatcher->onWindowInfosChanged(
1868 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001869
1870 // While this new obscuring window is present, the hovering continues. The event can't go to the
1871 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
1872 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1873 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1874 .build());
1875 obscuringWindow->assertNoEvents();
1876 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1877
1878 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001879 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001880
1881 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
1882 // so it should generate a HOVER_ENTER
1883 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1884 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1885 .build());
1886 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1887
1888 // Now the MOVE should be getting dispatched normally
1889 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1890 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
1891 .build());
1892 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1893}
1894
1895/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001896 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
1897 * events are delivered to the window.
1898 */
1899TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
1900 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001901 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1902 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001903 window->setFrame(Rect(0, 0, 200, 200));
1904 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1905
1906 // Start hovering in the window
1907 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
1908 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1909 .build());
1910 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1911
1912 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1913 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1914 .build());
1915 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1916
1917 // Scroll with the mouse
1918 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
1919 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1920 .build());
1921 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
1922}
1923
1924using InputDispatcherMultiDeviceTest = InputDispatcherTest;
1925
1926/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001927 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
1928 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001929 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001930TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001931 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001932 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001933 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1934 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001935 window->setFrame(Rect(0, 0, 200, 200));
1936
1937 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1938
1939 constexpr int32_t touchDeviceId = 4;
1940 constexpr int32_t stylusDeviceId = 2;
1941
1942 // Stylus down
1943 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1944 .deviceId(stylusDeviceId)
1945 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
1946 .build());
1947 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
1948
1949 // Touch down
1950 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1951 .deviceId(touchDeviceId)
1952 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
1953 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001954
1955 // Touch move
1956 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1957 .deviceId(touchDeviceId)
1958 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
1959 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001960 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001961
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001962 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001963 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
1964 .deviceId(stylusDeviceId)
1965 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
1966 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07001967 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
1968 WithCoords(101, 111)));
1969
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001970 window->assertNoEvents();
1971}
1972
1973/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001974 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
1975 * touch is not dropped, because multiple devices are allowed to be active in the same window.
1976 */
1977TEST_F(InputDispatcherMultiDeviceTest, StylusDownDoesNotBlockTouchDown) {
1978 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1979 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001980 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1981 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001982 window->setFrame(Rect(0, 0, 200, 200));
1983
1984 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1985
1986 constexpr int32_t touchDeviceId = 4;
1987 constexpr int32_t stylusDeviceId = 2;
1988
1989 // Stylus down
1990 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
1991 .deviceId(stylusDeviceId)
1992 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
1993 .build());
1994 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
1995
1996 // Touch down
1997 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1998 .deviceId(touchDeviceId)
1999 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2000 .build());
2001 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2002
2003 // Touch move
2004 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2005 .deviceId(touchDeviceId)
2006 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2007 .build());
2008 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2009
2010 // Stylus move
2011 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2012 .deviceId(stylusDeviceId)
2013 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2014 .build());
2015 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2016 WithCoords(101, 111)));
2017
2018 window->assertNoEvents();
2019}
2020
2021/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002022 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002023 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002024 * Similar test as above, but with added SPY window.
2025 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002026TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002027 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002028 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002029 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2030 ui::LogicalDisplayId::DEFAULT);
2031 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2032 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002033 spyWindow->setFrame(Rect(0, 0, 200, 200));
2034 spyWindow->setTrustedOverlay(true);
2035 spyWindow->setSpy(true);
2036 window->setFrame(Rect(0, 0, 200, 200));
2037
2038 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2039
2040 constexpr int32_t touchDeviceId = 4;
2041 constexpr int32_t stylusDeviceId = 2;
2042
2043 // Stylus down
2044 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2045 .deviceId(stylusDeviceId)
2046 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2047 .build());
2048 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2049 spyWindow->consumeMotionEvent(
2050 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2051
2052 // Touch down
2053 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2054 .deviceId(touchDeviceId)
2055 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2056 .build());
2057
2058 // Touch move
2059 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2060 .deviceId(touchDeviceId)
2061 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2062 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002063
2064 // Touch is ignored because stylus is already down
2065
2066 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002067 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2068 .deviceId(stylusDeviceId)
2069 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2070 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002071 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2072 WithCoords(101, 111)));
2073 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2074 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002075
2076 window->assertNoEvents();
2077 spyWindow->assertNoEvents();
2078}
2079
2080/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002081 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2082 * down. Ensure that touch is not dropped, because multiple devices can be active at the same time.
2083 * Similar test as above, but with added SPY window.
2084 */
2085TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyDoesNotBlockTouchDown) {
2086 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2087 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002088 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2089 ui::LogicalDisplayId::DEFAULT);
2090 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2091 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002092 spyWindow->setFrame(Rect(0, 0, 200, 200));
2093 spyWindow->setTrustedOverlay(true);
2094 spyWindow->setSpy(true);
2095 window->setFrame(Rect(0, 0, 200, 200));
2096
2097 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2098
2099 constexpr int32_t touchDeviceId = 4;
2100 constexpr int32_t stylusDeviceId = 2;
2101
2102 // Stylus down
2103 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2104 .deviceId(stylusDeviceId)
2105 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2106 .build());
2107 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2108 spyWindow->consumeMotionEvent(
2109 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2110
2111 // Touch down
2112 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2113 .deviceId(touchDeviceId)
2114 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2115 .build());
2116 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2117 spyWindow->consumeMotionEvent(
2118 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2119
2120 // Touch move
2121 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2122 .deviceId(touchDeviceId)
2123 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2124 .build());
2125 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2126 spyWindow->consumeMotionEvent(
2127 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2128
2129 // Subsequent stylus movements are delivered correctly
2130 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2131 .deviceId(stylusDeviceId)
2132 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2133 .build());
2134 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2135 WithCoords(101, 111)));
2136 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2137 WithCoords(101, 111)));
2138
2139 window->assertNoEvents();
2140 spyWindow->assertNoEvents();
2141}
2142
2143/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002144 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002145 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002146 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002147TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002148 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002149 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002150 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2151 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002152 window->setFrame(Rect(0, 0, 200, 200));
2153
2154 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2155
2156 constexpr int32_t touchDeviceId = 4;
2157 constexpr int32_t stylusDeviceId = 2;
2158
2159 // Stylus down on the window
2160 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2161 .deviceId(stylusDeviceId)
2162 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2163 .build());
2164 window->consumeMotionEvent(
2165 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2166
2167 // Touch down on window
2168 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2169 .deviceId(touchDeviceId)
2170 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2171 .build());
2172 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2173 .deviceId(touchDeviceId)
2174 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2175 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002176
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002177 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002178
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002179 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002180 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2181 .deviceId(stylusDeviceId)
2182 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2183 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002184 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2185 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002186
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002187 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002188 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2189 .deviceId(touchDeviceId)
2190 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2191 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002192 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002193}
2194
2195/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002196 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2197 * touch is not dropped, because stylus hover and touch can be both active at the same time.
2198 */
2199TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
2200 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2201 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002202 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2203 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002204 window->setFrame(Rect(0, 0, 200, 200));
2205
2206 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2207
2208 constexpr int32_t touchDeviceId = 4;
2209 constexpr int32_t stylusDeviceId = 2;
2210
2211 // Stylus down on the window
2212 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2213 .deviceId(stylusDeviceId)
2214 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2215 .build());
2216 window->consumeMotionEvent(
2217 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2218
2219 // Touch down on window
2220 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2221 .deviceId(touchDeviceId)
2222 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2223 .build());
2224 // Touch move on window
2225 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2226 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2227 .deviceId(touchDeviceId)
2228 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2229 .build());
2230 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2231
2232 // Subsequent stylus movements are delivered correctly
2233 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2234 .deviceId(stylusDeviceId)
2235 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2236 .build());
2237 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2238 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2239
2240 // and subsequent touches continue to work
2241 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2242 .deviceId(touchDeviceId)
2243 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2244 .build());
2245 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2246 window->assertNoEvents();
2247}
2248
2249/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002250 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002251 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002252 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002253TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002254 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002255 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002256 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2257 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002258 window->setFrame(Rect(0, 0, 200, 200));
2259
2260 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2261
2262 constexpr int32_t touchDeviceId = 4;
2263 constexpr int32_t stylusDeviceId = 2;
2264
2265 // Touch down on window
2266 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2267 .deviceId(touchDeviceId)
2268 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2269 .build());
2270 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2271 .deviceId(touchDeviceId)
2272 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2273 .build());
2274 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2275 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2276
2277 // Stylus hover on the window
2278 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2279 .deviceId(stylusDeviceId)
2280 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2281 .build());
2282 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2283 .deviceId(stylusDeviceId)
2284 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2285 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002286 // Stylus hover movement causes touch to be canceled
2287 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2288 WithCoords(141, 146)));
2289 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2290 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2291 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2292 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002293
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002294 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002295 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2296 .deviceId(touchDeviceId)
2297 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2298 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002299
2300 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002301}
2302
2303/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002304 * One window. Touch down on the window. Then, stylus hover on the window from another device.
2305 * Ensure that touch is not canceled, because stylus hover can be active at the same time as touch.
2306 */
2307TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2308 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2309 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002310 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2311 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002312 window->setFrame(Rect(0, 0, 200, 200));
2313
2314 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2315
2316 constexpr int32_t touchDeviceId = 4;
2317 constexpr int32_t stylusDeviceId = 2;
2318
2319 // Touch down on window
2320 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2321 .deviceId(touchDeviceId)
2322 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2323 .build());
2324 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2325 .deviceId(touchDeviceId)
2326 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2327 .build());
2328 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2329 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2330
2331 // Stylus hover on the window
2332 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2333 .deviceId(stylusDeviceId)
2334 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2335 .build());
2336 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2337 .deviceId(stylusDeviceId)
2338 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2339 .build());
2340 // Stylus hover movement is received normally
2341 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2342 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2343 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2344 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2345
2346 // Subsequent touch movements also work
2347 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2348 .deviceId(touchDeviceId)
2349 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2350 .build());
2351 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2352 WithCoords(142, 147)));
2353
2354 window->assertNoEvents();
2355}
2356
2357/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002358 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2359 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2360 * become active.
2361 */
2362TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002363 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002364 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002365 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2366 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002367 window->setFrame(Rect(0, 0, 200, 200));
2368
2369 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2370
2371 constexpr int32_t stylusDeviceId1 = 3;
2372 constexpr int32_t stylusDeviceId2 = 5;
2373
2374 // Touch down on window
2375 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2376 .deviceId(stylusDeviceId1)
2377 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2378 .build());
2379 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2380 .deviceId(stylusDeviceId1)
2381 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2382 .build());
2383 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2384 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2385
2386 // Second stylus down
2387 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2388 .deviceId(stylusDeviceId2)
2389 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2390 .build());
2391 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2392 .deviceId(stylusDeviceId2)
2393 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2394 .build());
2395
2396 // First stylus is canceled, second one takes over.
2397 window->consumeMotionEvent(
2398 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2399 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2400 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2401
2402 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2403 .deviceId(stylusDeviceId1)
2404 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2405 .build());
2406 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002407 window->assertNoEvents();
2408}
2409
2410/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002411 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2412 * both stylus devices can function simultaneously.
2413 */
2414TEST_F(InputDispatcherMultiDeviceTest, TwoStylusDevicesActiveAtTheSameTime) {
2415 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2416 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002417 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2418 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002419 window->setFrame(Rect(0, 0, 200, 200));
2420
2421 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2422
2423 constexpr int32_t stylusDeviceId1 = 3;
2424 constexpr int32_t stylusDeviceId2 = 5;
2425
2426 // Touch down on window
2427 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2428 .deviceId(stylusDeviceId1)
2429 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2430 .build());
2431 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2432 .deviceId(stylusDeviceId1)
2433 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2434 .build());
2435 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2436 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2437
2438 // Second stylus down
2439 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2440 .deviceId(stylusDeviceId2)
2441 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2442 .build());
2443 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2444 .deviceId(stylusDeviceId2)
2445 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2446 .build());
2447 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2448 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2449
2450 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2451 .deviceId(stylusDeviceId1)
2452 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2453 .build());
2454 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2455 window->assertNoEvents();
2456}
2457
2458/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002459 * One window. Touch down on the window. Then, stylus down on the window from another device.
2460 * Ensure that is canceled, because stylus down should be preferred over touch.
2461 */
2462TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002463 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002464 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002465 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2466 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002467 window->setFrame(Rect(0, 0, 200, 200));
2468
2469 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2470
2471 constexpr int32_t touchDeviceId = 4;
2472 constexpr int32_t stylusDeviceId = 2;
2473
2474 // Touch down on window
2475 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2476 .deviceId(touchDeviceId)
2477 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2478 .build());
2479 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2480 .deviceId(touchDeviceId)
2481 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2482 .build());
2483 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2484 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2485
2486 // Stylus down on the window
2487 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2488 .deviceId(stylusDeviceId)
2489 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2490 .build());
2491 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2492 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2493
2494 // Subsequent stylus movements are delivered correctly
2495 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2496 .deviceId(stylusDeviceId)
2497 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2498 .build());
2499 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2500 WithCoords(101, 111)));
2501}
2502
2503/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002504 * One window. Touch down on the window. Then, stylus down on the window from another device.
2505 * Ensure that both touch and stylus are functioning independently.
2506 */
2507TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusDown) {
2508 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2509 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002510 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2511 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002512 window->setFrame(Rect(0, 0, 200, 200));
2513
2514 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2515
2516 constexpr int32_t touchDeviceId = 4;
2517 constexpr int32_t stylusDeviceId = 2;
2518
2519 // Touch down on window
2520 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2521 .deviceId(touchDeviceId)
2522 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2523 .build());
2524 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2525 .deviceId(touchDeviceId)
2526 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2527 .build());
2528 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2529 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2530
2531 // Stylus down on the window
2532 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2533 .deviceId(stylusDeviceId)
2534 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2535 .build());
2536 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2537
2538 // Subsequent stylus movements are delivered correctly
2539 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2540 .deviceId(stylusDeviceId)
2541 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2542 .build());
2543 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2544 WithCoords(101, 111)));
2545
2546 // Touch continues to work too
2547 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2548 .deviceId(touchDeviceId)
2549 .pointer(PointerBuilder(0, ToolType::FINGER).x(148).y(149))
2550 .build());
2551 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2552}
2553
2554/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002555 * Two windows: a window on the left and a window on the right.
2556 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2557 * down. Then, on the left window, also place second touch pointer down.
2558 * This test tries to reproduce a crash.
2559 * In the buggy implementation, second pointer down on the left window would cause a crash.
2560 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002561TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch_legacy) {
2562 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002563 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002564 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2565 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002566 leftWindow->setFrame(Rect(0, 0, 200, 200));
2567
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002568 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2569 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002570 rightWindow->setFrame(Rect(200, 0, 400, 200));
2571
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002572 mDispatcher->onWindowInfosChanged(
2573 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002574
2575 const int32_t touchDeviceId = 4;
2576 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002577
2578 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002579 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2580 .deviceId(mouseDeviceId)
2581 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2582 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002583 leftWindow->consumeMotionEvent(
2584 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2585
2586 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002587 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2588 .deviceId(mouseDeviceId)
2589 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2590 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2591 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002592
2593 leftWindow->consumeMotionEvent(
2594 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2595 leftWindow->consumeMotionEvent(
2596 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2597
Prabir Pradhan678438e2023-04-13 19:32:51 +00002598 mDispatcher->notifyMotion(
2599 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2600 .deviceId(mouseDeviceId)
2601 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2602 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2603 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2604 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002605 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2606
2607 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002608 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2609 .deviceId(touchDeviceId)
2610 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2611 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002612 leftWindow->assertNoEvents();
2613
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002614 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2615
2616 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002617 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2618 .deviceId(touchDeviceId)
2619 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2620 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2621 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002622 // Since this is now a new splittable pointer going down on the left window, and it's coming
2623 // from a different device, the current gesture in the left window (pointer down) should first
2624 // be canceled.
2625 leftWindow->consumeMotionEvent(
2626 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002627 leftWindow->consumeMotionEvent(
2628 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2629 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2630 // current implementation.
2631 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2632 rightWindow->consumeMotionEvent(
2633 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2634
2635 leftWindow->assertNoEvents();
2636 rightWindow->assertNoEvents();
2637}
2638
2639/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002640 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002641 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2642 * down. Then, on the left window, also place second touch pointer down.
2643 * This test tries to reproduce a crash.
2644 * In the buggy implementation, second pointer down on the left window would cause a crash.
2645 */
2646TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
2647 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2648 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002649 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2650 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002651 leftWindow->setFrame(Rect(0, 0, 200, 200));
2652
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002653 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2654 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002655 rightWindow->setFrame(Rect(200, 0, 400, 200));
2656
2657 mDispatcher->onWindowInfosChanged(
2658 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2659
2660 const int32_t touchDeviceId = 4;
2661 const int32_t mouseDeviceId = 6;
2662
2663 // Start hovering over the left window
2664 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2665 .deviceId(mouseDeviceId)
2666 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2667 .build());
2668 leftWindow->consumeMotionEvent(
2669 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2670
2671 // Mouse down on left window
2672 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2673 .deviceId(mouseDeviceId)
2674 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2675 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2676 .build());
2677
2678 leftWindow->consumeMotionEvent(
2679 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2680 leftWindow->consumeMotionEvent(
2681 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2682
2683 mDispatcher->notifyMotion(
2684 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2685 .deviceId(mouseDeviceId)
2686 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2687 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2688 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2689 .build());
2690 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2691
2692 // First touch pointer down on right window
2693 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2694 .deviceId(touchDeviceId)
2695 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2696 .build());
2697 leftWindow->assertNoEvents();
2698
2699 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2700
2701 // Second touch pointer down on left window
2702 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2703 .deviceId(touchDeviceId)
2704 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2705 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2706 .build());
2707 // Since this is now a new splittable pointer going down on the left window, and it's coming
2708 // from a different device, it will be split and delivered to left window separately.
2709 leftWindow->consumeMotionEvent(
2710 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2711 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2712 // current implementation.
2713 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2714 rightWindow->consumeMotionEvent(
2715 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2716
2717 leftWindow->assertNoEvents();
2718 rightWindow->assertNoEvents();
2719}
2720
2721/**
2722 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002723 * Mouse is hovered on the left window and stylus is hovered on the right window.
2724 */
2725TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2726 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002727 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2728 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002729 leftWindow->setFrame(Rect(0, 0, 200, 200));
2730
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002731 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2732 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002733 rightWindow->setFrame(Rect(200, 0, 400, 200));
2734
2735 mDispatcher->onWindowInfosChanged(
2736 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2737
2738 const int32_t stylusDeviceId = 3;
2739 const int32_t mouseDeviceId = 6;
2740
2741 // Start hovering over the left window
2742 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2743 .deviceId(mouseDeviceId)
2744 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2745 .build());
2746 leftWindow->consumeMotionEvent(
2747 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2748
2749 // Stylus hovered on right window
2750 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2751 .deviceId(stylusDeviceId)
2752 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2753 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002754 rightWindow->consumeMotionEvent(
2755 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2756
2757 // Subsequent HOVER_MOVE events are dispatched correctly.
2758 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2759 .deviceId(mouseDeviceId)
2760 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2761 .build());
2762 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002763 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002764
2765 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2766 .deviceId(stylusDeviceId)
2767 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2768 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002769 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002770 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002771
2772 leftWindow->assertNoEvents();
2773 rightWindow->assertNoEvents();
2774}
2775
2776/**
2777 * Three windows: a window on the left and a window on the right.
2778 * And a spy window that's positioned above all of them.
2779 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2780 * Check the stream that's received by the spy.
2781 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002782TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy_legacy) {
2783 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002784 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2785
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002786 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2787 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002788 spyWindow->setFrame(Rect(0, 0, 400, 400));
2789 spyWindow->setTrustedOverlay(true);
2790 spyWindow->setSpy(true);
2791
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002792 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2793 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002794 leftWindow->setFrame(Rect(0, 0, 200, 200));
2795
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002796 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2797 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002798
2799 rightWindow->setFrame(Rect(200, 0, 400, 200));
2800
2801 mDispatcher->onWindowInfosChanged(
2802 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2803
2804 const int32_t stylusDeviceId = 1;
2805 const int32_t touchDeviceId = 2;
2806
2807 // Stylus down on the left window
2808 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2809 .deviceId(stylusDeviceId)
2810 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2811 .build());
2812 leftWindow->consumeMotionEvent(
2813 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2814 spyWindow->consumeMotionEvent(
2815 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2816
2817 // Touch down on the right window
2818 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2819 .deviceId(touchDeviceId)
2820 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2821 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002822 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002823 rightWindow->consumeMotionEvent(
2824 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002825
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002826 // Spy window does not receive touch events, because stylus events take precedence, and it
2827 // already has an active stylus gesture.
2828
2829 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002830 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2831 .deviceId(stylusDeviceId)
2832 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2833 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002834 leftWindow->consumeMotionEvent(
2835 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2836 spyWindow->consumeMotionEvent(
2837 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002838
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002839 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002840 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2841 .deviceId(touchDeviceId)
2842 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2843 .build());
2844 rightWindow->consumeMotionEvent(
2845 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002846
2847 spyWindow->assertNoEvents();
2848 leftWindow->assertNoEvents();
2849 rightWindow->assertNoEvents();
2850}
2851
2852/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002853 * Three windows: a window on the left and a window on the right.
2854 * And a spy window that's positioned above all of them.
2855 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2856 * Check the stream that's received by the spy.
2857 */
2858TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2859 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2860 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2861
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002862 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2863 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002864 spyWindow->setFrame(Rect(0, 0, 400, 400));
2865 spyWindow->setTrustedOverlay(true);
2866 spyWindow->setSpy(true);
2867
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002868 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2869 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002870 leftWindow->setFrame(Rect(0, 0, 200, 200));
2871
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002872 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2873 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002874
2875 rightWindow->setFrame(Rect(200, 0, 400, 200));
2876
2877 mDispatcher->onWindowInfosChanged(
2878 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2879
2880 const int32_t stylusDeviceId = 1;
2881 const int32_t touchDeviceId = 2;
2882
2883 // Stylus down on the left window
2884 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2885 .deviceId(stylusDeviceId)
2886 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2887 .build());
2888 leftWindow->consumeMotionEvent(
2889 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2890 spyWindow->consumeMotionEvent(
2891 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2892
2893 // Touch down on the right window
2894 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2895 .deviceId(touchDeviceId)
2896 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2897 .build());
2898 leftWindow->assertNoEvents();
2899 rightWindow->consumeMotionEvent(
2900 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2901 spyWindow->consumeMotionEvent(
2902 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2903
2904 // Stylus movements continue. They should be delivered to the left window and to the spy window
2905 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2906 .deviceId(stylusDeviceId)
2907 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2908 .build());
2909 leftWindow->consumeMotionEvent(
2910 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2911 spyWindow->consumeMotionEvent(
2912 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2913
2914 // Further touch MOVE events keep going to the right window and to the spy
2915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2916 .deviceId(touchDeviceId)
2917 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2918 .build());
2919 rightWindow->consumeMotionEvent(
2920 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2921 spyWindow->consumeMotionEvent(
2922 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2923
2924 spyWindow->assertNoEvents();
2925 leftWindow->assertNoEvents();
2926 rightWindow->assertNoEvents();
2927}
2928
2929/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002930 * Three windows: a window on the left, a window on the right, and a spy window positioned above
2931 * both.
2932 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002933 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002934 * At the same time, left and right should be getting independent streams of hovering and touch,
2935 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002936 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002937TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002938 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002939 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2940
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002941 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2942 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002943 spyWindow->setFrame(Rect(0, 0, 400, 400));
2944 spyWindow->setTrustedOverlay(true);
2945 spyWindow->setSpy(true);
2946
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002947 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2948 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002949 leftWindow->setFrame(Rect(0, 0, 200, 200));
2950
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002951 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2952 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002953 rightWindow->setFrame(Rect(200, 0, 400, 200));
2954
2955 mDispatcher->onWindowInfosChanged(
2956 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2957
2958 const int32_t stylusDeviceId = 1;
2959 const int32_t touchDeviceId = 2;
2960
2961 // Stylus hover on the left window
2962 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2963 .deviceId(stylusDeviceId)
2964 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2965 .build());
2966 leftWindow->consumeMotionEvent(
2967 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2968 spyWindow->consumeMotionEvent(
2969 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2970
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002971 // Touch down on the right window. Spy doesn't receive this touch because it already has
2972 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002973 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2974 .deviceId(touchDeviceId)
2975 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2976 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002977 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002978 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002979 rightWindow->consumeMotionEvent(
2980 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2981
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002982 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002983 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2984 .deviceId(stylusDeviceId)
2985 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2986 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002987 leftWindow->consumeMotionEvent(
2988 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002989 spyWindow->consumeMotionEvent(
2990 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002991
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002992 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002993 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2994 .deviceId(touchDeviceId)
2995 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
2996 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002997 rightWindow->consumeMotionEvent(
2998 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2999
3000 spyWindow->assertNoEvents();
3001 leftWindow->assertNoEvents();
3002 rightWindow->assertNoEvents();
3003}
3004
3005/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003006 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3007 * both.
3008 * Check hover in left window and touch down in the right window.
3009 * At first, spy should receive hover. Next, spy should receive touch.
3010 * At the same time, left and right should be getting independent streams of hovering and touch,
3011 * respectively.
3012 */
3013TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverDoesNotBlockTouchWithSpy) {
3014 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3015 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3016
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003017 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3018 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003019 spyWindow->setFrame(Rect(0, 0, 400, 400));
3020 spyWindow->setTrustedOverlay(true);
3021 spyWindow->setSpy(true);
3022
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003023 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3024 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003025 leftWindow->setFrame(Rect(0, 0, 200, 200));
3026
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003027 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3028 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003029 rightWindow->setFrame(Rect(200, 0, 400, 200));
3030
3031 mDispatcher->onWindowInfosChanged(
3032 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3033
3034 const int32_t stylusDeviceId = 1;
3035 const int32_t touchDeviceId = 2;
3036
3037 // Stylus hover on the left window
3038 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3039 .deviceId(stylusDeviceId)
3040 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3041 .build());
3042 leftWindow->consumeMotionEvent(
3043 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3044 spyWindow->consumeMotionEvent(
3045 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3046
3047 // Touch down on the right window.
3048 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3049 .deviceId(touchDeviceId)
3050 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3051 .build());
3052 leftWindow->assertNoEvents();
3053 spyWindow->consumeMotionEvent(
3054 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3055 rightWindow->consumeMotionEvent(
3056 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3057
3058 // Stylus movements continue. They should be delivered to the left window and the spy.
3059 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3060 .deviceId(stylusDeviceId)
3061 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3062 .build());
3063 leftWindow->consumeMotionEvent(
3064 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3065 spyWindow->consumeMotionEvent(
3066 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3067
3068 // Touch movements continue. They should be delivered to the right window and the spy
3069 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3070 .deviceId(touchDeviceId)
3071 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3072 .build());
3073 rightWindow->consumeMotionEvent(
3074 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3075 spyWindow->consumeMotionEvent(
3076 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3077
3078 spyWindow->assertNoEvents();
3079 leftWindow->assertNoEvents();
3080 rightWindow->assertNoEvents();
3081}
3082
3083/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003084 * On a single window, use two different devices: mouse and touch.
3085 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3086 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3087 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3088 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3089 * represent a new gesture.
3090 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003091TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown_legacy) {
3092 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003093 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003094 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3095 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003096 window->setFrame(Rect(0, 0, 400, 400));
3097
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003098 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003099
3100 const int32_t touchDeviceId = 4;
3101 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003102
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003103 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003104 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3105 .deviceId(touchDeviceId)
3106 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3107 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003108 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003109 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3110 .deviceId(touchDeviceId)
3111 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3112 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3113 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003114 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003115 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3116 .deviceId(touchDeviceId)
3117 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3118 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3119 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003120 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3121 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3122 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3123
3124 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003125 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3126 .deviceId(mouseDeviceId)
3127 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3128 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3129 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003130
3131 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003132 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003133 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3134
Prabir Pradhan678438e2023-04-13 19:32:51 +00003135 mDispatcher->notifyMotion(
3136 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3137 .deviceId(mouseDeviceId)
3138 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3139 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3140 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3141 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003142 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3143
3144 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003145 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3146 .deviceId(touchDeviceId)
3147 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3148 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3149 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003150 // Since we already canceled this touch gesture, it will be ignored until a completely new
3151 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3152 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3153 // However, mouse movements should continue to work.
3154 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3155 .deviceId(mouseDeviceId)
3156 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3157 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3158 .build());
3159 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3160
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003161 window->assertNoEvents();
3162}
3163
3164/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003165 * On a single window, use two different devices: mouse and touch.
3166 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3167 * Mouse is clicked next, which should not interfere with the touch stream.
3168 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is also
3169 * delivered correctly.
3170 */
3171TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
3172 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3173 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003174 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3175 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003176 window->setFrame(Rect(0, 0, 400, 400));
3177
3178 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3179
3180 const int32_t touchDeviceId = 4;
3181 const int32_t mouseDeviceId = 6;
3182
3183 // First touch pointer down
3184 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3185 .deviceId(touchDeviceId)
3186 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3187 .build());
3188 // Second touch pointer down
3189 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3190 .deviceId(touchDeviceId)
3191 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3192 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3193 .build());
3194 // First touch pointer lifts. The second one remains down
3195 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3196 .deviceId(touchDeviceId)
3197 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3198 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3199 .build());
3200 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3201 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3202 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3203
3204 // Mouse down
3205 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3206 .deviceId(mouseDeviceId)
3207 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3208 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3209 .build());
3210
3211 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3212
3213 mDispatcher->notifyMotion(
3214 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3215 .deviceId(mouseDeviceId)
3216 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3217 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3218 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3219 .build());
3220 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3221
3222 // Second touch pointer down.
3223 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3224 .deviceId(touchDeviceId)
3225 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3226 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3227 .build());
3228 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_0_DOWN), WithDeviceId(touchDeviceId),
3229 WithPointerCount(2u)));
3230
3231 // Mouse movements should continue to work
3232 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3233 .deviceId(mouseDeviceId)
3234 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3235 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3236 .build());
3237 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3238
3239 window->assertNoEvents();
3240}
3241
3242/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003243 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3244 * the injected event.
3245 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003246TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent_legacy) {
3247 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003248 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003249 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3250 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003251 window->setFrame(Rect(0, 0, 400, 400));
3252
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003253 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003254
3255 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003256 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3257 // completion.
3258 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003259 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003260 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3261 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003262 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003263 .build()));
3264 window->consumeMotionEvent(
3265 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3266
3267 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3268 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003269 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3270 .deviceId(touchDeviceId)
3271 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3272 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003273
3274 window->consumeMotionEvent(
3275 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3276 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3277}
3278
3279/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003280 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event runs
3281 * parallel to the injected event.
3282 */
3283TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
3284 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3285 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003286 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3287 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003288 window->setFrame(Rect(0, 0, 400, 400));
3289
3290 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3291
3292 const int32_t touchDeviceId = 4;
3293 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3294 // completion.
3295 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3296 injectMotionEvent(*mDispatcher,
3297 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3298 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
3299 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3300 .build()));
3301 window->consumeMotionEvent(
3302 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3303
3304 // Now a real touch comes. The injected pointer will remain, and the new gesture will also be
3305 // allowed through.
3306 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3307 .deviceId(touchDeviceId)
3308 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3309 .build());
3310 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3311}
3312
3313/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003314 * This test is similar to the test above, but the sequence of injected events is different.
3315 *
3316 * Two windows: a window on the left and a window on the right.
3317 * Mouse is hovered over the left window.
3318 * Next, we tap on the left window, where the cursor was last seen.
3319 *
3320 * After that, we inject one finger down onto the right window, and then a second finger down onto
3321 * the left window.
3322 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3323 * window (first), and then another on the left window (second).
3324 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3325 * In the buggy implementation, second finger down on the left window would cause a crash.
3326 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003327TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch_legacy) {
3328 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003329 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003330 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3331 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003332 leftWindow->setFrame(Rect(0, 0, 200, 200));
3333
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003334 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3335 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003336 rightWindow->setFrame(Rect(200, 0, 400, 200));
3337
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003338 mDispatcher->onWindowInfosChanged(
3339 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003340
3341 const int32_t mouseDeviceId = 6;
3342 const int32_t touchDeviceId = 4;
3343 // Hover over the left window. Keep the cursor there.
3344 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003345 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003346 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3347 AINPUT_SOURCE_MOUSE)
3348 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003349 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003350 .build()));
3351 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3352
3353 // Tap on left window
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_DOWN,
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
3362 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003363 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003364 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3365 AINPUT_SOURCE_TOUCHSCREEN)
3366 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003367 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003368 .build()));
3369 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3370 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3371 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3372
3373 // First finger down on right window
3374 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003375 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003376 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3377 AINPUT_SOURCE_TOUCHSCREEN)
3378 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003379 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003380 .build()));
3381 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3382
3383 // Second finger down on the left window
3384 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003385 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003386 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3387 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003388 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3389 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003390 .build()));
3391 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3392 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3393
3394 // No more events
3395 leftWindow->assertNoEvents();
3396 rightWindow->assertNoEvents();
3397}
3398
3399/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003400 * This test is similar to the test above, but the sequence of injected events is different.
3401 *
3402 * Two windows: a window on the left and a window on the right.
3403 * Mouse is hovered over the left window.
3404 * Next, we tap on the left window, where the cursor was last seen.
3405 *
3406 * After that, we send one finger down onto the right window, and then a second finger down onto
3407 * the left window.
3408 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3409 * window (first), and then another on the left window (second).
3410 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3411 * In the buggy implementation, second finger down on the left window would cause a crash.
3412 */
3413TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
3414 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3415 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003416 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3417 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003418 leftWindow->setFrame(Rect(0, 0, 200, 200));
3419
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003420 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3421 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003422 rightWindow->setFrame(Rect(200, 0, 400, 200));
3423
3424 mDispatcher->onWindowInfosChanged(
3425 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3426
3427 const int32_t mouseDeviceId = 6;
3428 const int32_t touchDeviceId = 4;
3429 // Hover over the left window. Keep the cursor there.
3430 mDispatcher->notifyMotion(
3431 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3432 .deviceId(mouseDeviceId)
3433 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3434 .build());
3435 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3436
3437 // Tap on left window
3438 mDispatcher->notifyMotion(
3439 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3440 .deviceId(touchDeviceId)
3441 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3442 .build());
3443
3444 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3445 .deviceId(touchDeviceId)
3446 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3447 .build());
3448 leftWindow->consumeMotionEvent(
3449 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithDeviceId(touchDeviceId)));
3450 leftWindow->consumeMotionEvent(
3451 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithDeviceId(touchDeviceId)));
3452
3453 // First finger down on right window
3454 mDispatcher->notifyMotion(
3455 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3456 .deviceId(touchDeviceId)
3457 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3458 .build());
3459 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3460
3461 // Second finger down on the left window
3462 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3463 .deviceId(touchDeviceId)
3464 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3465 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
3466 .build());
3467 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3468 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3469
3470 // No more events
3471 leftWindow->assertNoEvents();
3472 rightWindow->assertNoEvents();
3473}
3474
3475/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003476 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3477 * While the touch is down, new hover events from the stylus device should be ignored. After the
3478 * touch is gone, stylus hovering should start working again.
3479 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003480TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003481 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003482 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003483 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3484 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003485 window->setFrame(Rect(0, 0, 200, 200));
3486
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003487 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003488
3489 const int32_t stylusDeviceId = 5;
3490 const int32_t touchDeviceId = 4;
3491 // Start hovering with stylus
3492 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003493 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003494 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003495 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003496 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003497 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003498 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003499
3500 // Finger down on the window
3501 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003502 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003503 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003504 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003505 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003506 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003507 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003508
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003509 // Continue hovering with stylus.
3510 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003511 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003512 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3513 AINPUT_SOURCE_STYLUS)
3514 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003515 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003516 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003517 // Hovers continue to work
3518 window->consumeMotionEvent(
3519 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003520
3521 // Lift up the finger
3522 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_UP,
3525 AINPUT_SOURCE_TOUCHSCREEN)
3526 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003527 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003528 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003529
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003530 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003531 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003532 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3533 AINPUT_SOURCE_STYLUS)
3534 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003535 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003536 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003537 window->consumeMotionEvent(
3538 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003539 window->assertNoEvents();
3540}
3541
3542/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003543 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3544 * While the touch is down, hovering from the stylus is not affected. After the touch is gone,
3545 * check that the stylus hovering continues to work.
3546 */
3547TEST_F(InputDispatcherMultiDeviceTest, StylusHoverWithTouchTap) {
3548 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3549 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003550 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3551 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003552 window->setFrame(Rect(0, 0, 200, 200));
3553
3554 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3555
3556 const int32_t stylusDeviceId = 5;
3557 const int32_t touchDeviceId = 4;
3558 // Start hovering with stylus
3559 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3560 .deviceId(stylusDeviceId)
3561 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3562 .build());
3563 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3564
3565 // Finger down on the window
3566 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3567 .deviceId(touchDeviceId)
3568 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3569 .build());
3570 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3571
3572 // Continue hovering with stylus.
3573 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3574 .deviceId(stylusDeviceId)
3575 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
3576 .build());
3577 // Hovers continue to work
3578 window->consumeMotionEvent(
3579 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3580
3581 // Lift up the finger
3582 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3583 .deviceId(touchDeviceId)
3584 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3585 .build());
3586 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
3587
3588 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3589 .deviceId(stylusDeviceId)
3590 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
3591 .build());
3592 window->consumeMotionEvent(
3593 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3594 window->assertNoEvents();
3595}
3596
3597/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003598 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3599 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3600 *
3601 * Two windows: one on the left and one on the right.
3602 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3603 * Stylus down on the left window, and then touch down on the right window.
3604 * Check that the right window doesn't get touches while the stylus is down on the left window.
3605 */
3606TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3607 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3608 sp<FakeWindowHandle> leftWindow =
3609 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003610 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003611 leftWindow->setFrame(Rect(0, 0, 100, 100));
3612
3613 sp<FakeWindowHandle> sbtRightWindow =
3614 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003615 "Stylus blocks touch (right) window",
3616 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003617 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3618 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3619
3620 mDispatcher->onWindowInfosChanged(
3621 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3622
3623 const int32_t stylusDeviceId = 5;
3624 const int32_t touchDeviceId = 4;
3625
3626 // Stylus down in the left window
3627 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3628 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3629 .deviceId(stylusDeviceId)
3630 .build());
3631 leftWindow->consumeMotionEvent(
3632 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3633
3634 // Finger tap on the right window
3635 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3636 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3637 .deviceId(touchDeviceId)
3638 .build());
3639 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3640 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3641 .deviceId(touchDeviceId)
3642 .build());
3643
3644 // The touch should be blocked, because stylus is down somewhere else on screen!
3645 sbtRightWindow->assertNoEvents();
3646
3647 // Continue stylus motion, and ensure it's not impacted.
3648 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3649 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3650 .deviceId(stylusDeviceId)
3651 .build());
3652 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3653 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3654 .deviceId(stylusDeviceId)
3655 .build());
3656 leftWindow->consumeMotionEvent(
3657 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3658 leftWindow->consumeMotionEvent(
3659 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3660
3661 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3662 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3663 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3664 .deviceId(touchDeviceId)
3665 .build());
3666 sbtRightWindow->consumeMotionEvent(
3667 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3668}
3669
3670/**
3671 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3672 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3673 *
3674 * Two windows: one on the left and one on the right.
3675 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3676 * Stylus hover on the left window, and then touch down on the right window.
3677 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3678 */
3679TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3680 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3681 sp<FakeWindowHandle> leftWindow =
3682 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003683 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003684 leftWindow->setFrame(Rect(0, 0, 100, 100));
3685
3686 sp<FakeWindowHandle> sbtRightWindow =
3687 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003688 "Stylus blocks touch (right) window",
3689 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003690 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3691 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3692
3693 mDispatcher->onWindowInfosChanged(
3694 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3695
3696 const int32_t stylusDeviceId = 5;
3697 const int32_t touchDeviceId = 4;
3698
3699 // Stylus hover in the left window
3700 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3701 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3702 .deviceId(stylusDeviceId)
3703 .build());
3704 leftWindow->consumeMotionEvent(
3705 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3706
3707 // Finger tap on the right window
3708 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3709 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3710 .deviceId(touchDeviceId)
3711 .build());
3712 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3713 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3714 .deviceId(touchDeviceId)
3715 .build());
3716
3717 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3718 sbtRightWindow->assertNoEvents();
3719
3720 // Continue stylus motion, and ensure it's not impacted.
3721 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3722 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3723 .deviceId(stylusDeviceId)
3724 .build());
3725 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3726 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3727 .deviceId(stylusDeviceId)
3728 .build());
3729 leftWindow->consumeMotionEvent(
3730 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3731 leftWindow->consumeMotionEvent(
3732 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3733
3734 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3735 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3736 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3737 .deviceId(touchDeviceId)
3738 .build());
3739 sbtRightWindow->consumeMotionEvent(
3740 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3741}
3742
3743/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003744 * A spy window above a window with no input channel.
3745 * Start hovering with a stylus device, and then tap with it.
3746 * Ensure spy window receives the entire sequence.
3747 */
3748TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3749 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003750 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3751 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003752 spyWindow->setFrame(Rect(0, 0, 200, 200));
3753 spyWindow->setTrustedOverlay(true);
3754 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003755 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3756 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003757 window->setNoInputChannel(true);
3758 window->setFrame(Rect(0, 0, 200, 200));
3759
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003760 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003761
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003762 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003763 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3764 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3765 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003766 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3767 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003768 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3769 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3770 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003771 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3772
3773 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003774 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3775 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3776 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003777 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3778
3779 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003780 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3781 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3782 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003783 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3784
3785 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003786 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3787 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3788 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003789 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3790 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003791 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3792 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3793 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003794 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3795
3796 // No more events
3797 spyWindow->assertNoEvents();
3798 window->assertNoEvents();
3799}
3800
3801/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003802 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3803 * rejected. But since we already have an ongoing gesture, this event should be processed.
3804 * This prevents inconsistent events being handled inside the dispatcher.
3805 */
3806TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3807 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3808
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003809 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3810 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003811 window->setFrame(Rect(0, 0, 200, 200));
3812
3813 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3814
3815 // Start hovering with stylus
3816 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3817 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3818 .build());
3819 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3820
3821 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3822 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3823 .build();
3824 // Make this 'hoverExit' event stale
3825 mFakePolicy->setStaleEventTimeout(100ms);
3826 std::this_thread::sleep_for(100ms);
3827
3828 // It shouldn't be dropped by the dispatcher, even though it's stale.
3829 mDispatcher->notifyMotion(hoverExit);
3830 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3831
3832 // Stylus starts hovering again! There should be no crash.
3833 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3834 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3835 .build());
3836 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3837}
3838
3839/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003840 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3841 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3842 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3843 * While the mouse is down, new move events from the touch device should be ignored.
3844 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003845TEST_F(InputDispatcherTest, TouchPilferAndMouseMove_legacy) {
3846 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003847 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003848 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3849 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003850 spyWindow->setFrame(Rect(0, 0, 200, 200));
3851 spyWindow->setTrustedOverlay(true);
3852 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003853 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3854 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003855 window->setFrame(Rect(0, 0, 200, 200));
3856
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003857 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003858
3859 const int32_t mouseDeviceId = 7;
3860 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003861
3862 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003863 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3864 .deviceId(mouseDeviceId)
3865 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3866 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003867 spyWindow->consumeMotionEvent(
3868 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3869 window->consumeMotionEvent(
3870 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3871
3872 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003873 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3874 .deviceId(touchDeviceId)
3875 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3876 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003877 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3878 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3879 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3880 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3881
Prabir Pradhan678438e2023-04-13 19:32:51 +00003882 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3883 .deviceId(touchDeviceId)
3884 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3885 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003886 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3887 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3888
3889 // Pilfer the stream
3890 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3891 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3892
Prabir Pradhan678438e2023-04-13 19:32:51 +00003893 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3894 .deviceId(touchDeviceId)
3895 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3896 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003897 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3898
3899 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003900 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3901 .deviceId(mouseDeviceId)
3902 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3903 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3904 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003905
3906 spyWindow->consumeMotionEvent(
3907 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3908 spyWindow->consumeMotionEvent(
3909 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3910 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3911
Prabir Pradhan678438e2023-04-13 19:32:51 +00003912 mDispatcher->notifyMotion(
3913 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3914 .deviceId(mouseDeviceId)
3915 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3916 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3917 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3918 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003919 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3920 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3921
3922 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003923 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3924 .deviceId(mouseDeviceId)
3925 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3926 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
3927 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003928 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3929 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3930
3931 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00003932 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3933 .deviceId(touchDeviceId)
3934 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
3935 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003936
3937 // No more events
3938 spyWindow->assertNoEvents();
3939 window->assertNoEvents();
3940}
3941
3942/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003943 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3944 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3945 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3946 * While the mouse is down, new move events from the touch device should continue to work.
3947 */
3948TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
3949 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3950 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003951 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3952 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003953 spyWindow->setFrame(Rect(0, 0, 200, 200));
3954 spyWindow->setTrustedOverlay(true);
3955 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003956 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3957 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003958 window->setFrame(Rect(0, 0, 200, 200));
3959
3960 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
3961
3962 const int32_t mouseDeviceId = 7;
3963 const int32_t touchDeviceId = 4;
3964
3965 // Hover a bit with mouse first
3966 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3967 .deviceId(mouseDeviceId)
3968 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3969 .build());
3970 spyWindow->consumeMotionEvent(
3971 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3972 window->consumeMotionEvent(
3973 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3974
3975 // Start touching
3976 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3977 .deviceId(touchDeviceId)
3978 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3979 .build());
3980
3981 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3982 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3983
3984 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3985 .deviceId(touchDeviceId)
3986 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3987 .build());
3988 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3989 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3990
3991 // Pilfer the stream
3992 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3993 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
3994 // Hover is not pilfered! Only touch.
3995
3996 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3997 .deviceId(touchDeviceId)
3998 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3999 .build());
4000 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4001
4002 // Mouse down
4003 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4004 .deviceId(mouseDeviceId)
4005 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4006 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4007 .build());
4008
4009 spyWindow->consumeMotionEvent(
4010 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4011 spyWindow->consumeMotionEvent(
4012 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4013 window->consumeMotionEvent(
4014 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4015 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4016
4017 mDispatcher->notifyMotion(
4018 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4019 .deviceId(mouseDeviceId)
4020 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4021 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4022 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4023 .build());
4024 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4025 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4026
4027 // Mouse move!
4028 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4029 .deviceId(mouseDeviceId)
4030 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4031 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4032 .build());
4033 spyWindow->consumeMotionEvent(
4034 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4035 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4036
4037 // Touch move!
4038 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4039 .deviceId(touchDeviceId)
4040 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4041 .build());
4042 spyWindow->consumeMotionEvent(
4043 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4044
4045 // No more events
4046 spyWindow->assertNoEvents();
4047 window->assertNoEvents();
4048}
4049
4050/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004051 * On the display, have a single window, and also an area where there's no window.
4052 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
4053 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
4054 */
4055TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
4056 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4057 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004058 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004059
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004060 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004061
4062 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00004063 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004064
4065 mDispatcher->waitForIdle();
4066 window->assertNoEvents();
4067
4068 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004069 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004070 mDispatcher->waitForIdle();
4071 window->consumeMotionDown();
4072}
4073
4074/**
4075 * Same test as above, but instead of touching the empty space, the first touch goes to
4076 * non-touchable window.
4077 */
4078TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
4079 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4080 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004081 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004082 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4083 window1->setTouchable(false);
4084 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004085 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004086 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4087
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004088 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004089
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004090 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004091 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004092
4093 mDispatcher->waitForIdle();
4094 window1->assertNoEvents();
4095 window2->assertNoEvents();
4096
4097 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004098 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004099 mDispatcher->waitForIdle();
4100 window2->consumeMotionDown();
4101}
4102
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004103/**
4104 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
4105 * to the event time of the first ACTION_DOWN sent to the particular window.
4106 */
4107TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
4108 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4109 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004110 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004111 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4112 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004113 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004114 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4115
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004116 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004117
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004118 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004119 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004120 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004121
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004122 const std::unique_ptr<MotionEvent> firstDown =
4123 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4124 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004125 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004126
4127 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004128 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004129 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004130
4131 const std::unique_ptr<MotionEvent> secondDown =
4132 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4133 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
4134 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
4135 // We currently send MOVE events to all windows receiving a split touch when there is any change
4136 // in the touch state, even when none of the pointers in the split window actually moved.
4137 // Document this behavior in the test.
4138 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004139
4140 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004141 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004142 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004143
4144 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4145 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004146
4147 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004148 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004149 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004150
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004151 window2->consumeMotionEvent(
4152 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
4153 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004154
4155 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004156 mDispatcher->notifyMotion(
4157 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004158 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004159
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004160 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
4161 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4162
4163 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004164 mDispatcher->notifyMotion(
4165 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004166 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004167
4168 window1->consumeMotionEvent(
4169 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
4170 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004171}
4172
Garfield Tandf26e862020-07-01 20:18:19 -07004173TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004174 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004175 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4176 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004177 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004178 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4179 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004180 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004181
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004182 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004183
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004184 mDispatcher->onWindowInfosChanged(
4185 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004186
4187 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004188 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004189 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004190 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4191 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004192 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004193 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004194 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004195
4196 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004198 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004199 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4200 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004201 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004202 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004203 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4204 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004205
4206 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004207 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004208 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004209 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4210 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004211 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004212 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004213 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4214 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004215
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004216 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004217 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004218 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4219 AINPUT_SOURCE_MOUSE)
4220 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4221 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004222 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004223 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004224 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004225
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004226 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004227 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004228 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4229 AINPUT_SOURCE_MOUSE)
4230 .buttonState(0)
4231 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004232 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004233 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004234 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004235
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004236 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004237 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004238 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4239 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004240 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004241 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004242 windowLeft->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004243
4244 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004246 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004247 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4248 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004249 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004250 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004251 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004252
4253 // No more events
4254 windowLeft->assertNoEvents();
4255 windowRight->assertNoEvents();
4256}
4257
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004258/**
4259 * Put two fingers down (and don't release them) and click the mouse button.
4260 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4261 * currently active gesture should be canceled, and the new one should proceed.
4262 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004263TEST_F(InputDispatcherTest, TwoPointersDownMouseClick_legacy) {
4264 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004265 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004266 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4267 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004268 window->setFrame(Rect(0, 0, 600, 800));
4269
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004270 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004271
4272 const int32_t touchDeviceId = 4;
4273 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004274
4275 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004276 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4277 .deviceId(touchDeviceId)
4278 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4279 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004280
Prabir Pradhan678438e2023-04-13 19:32:51 +00004281 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4282 .deviceId(touchDeviceId)
4283 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4284 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4285 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004286 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4287 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4288
4289 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004290 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4291 .deviceId(mouseDeviceId)
4292 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4293 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4294 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004295 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4296 WithPointerCount(2u)));
4297 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4298
Prabir Pradhan678438e2023-04-13 19:32:51 +00004299 mDispatcher->notifyMotion(
4300 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4301 .deviceId(mouseDeviceId)
4302 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4303 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4304 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4305 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004306 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4307
4308 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4309 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004310 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4311 .deviceId(touchDeviceId)
4312 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4313 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4314 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004315 window->assertNoEvents();
4316}
4317
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004318/**
4319 * Put two fingers down (and don't release them) and click the mouse button.
4320 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4321 * currently active gesture should not be canceled, and the new one should proceed in parallel.
4322 */
4323TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4324 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4325 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004326 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4327 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004328 window->setFrame(Rect(0, 0, 600, 800));
4329
4330 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4331
4332 const int32_t touchDeviceId = 4;
4333 const int32_t mouseDeviceId = 6;
4334
4335 // Two pointers down
4336 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4337 .deviceId(touchDeviceId)
4338 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4339 .build());
4340
4341 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4342 .deviceId(touchDeviceId)
4343 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4344 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4345 .build());
4346 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4347 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4348
4349 // Send a series of mouse events for a mouse click
4350 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4351 .deviceId(mouseDeviceId)
4352 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4353 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4354 .build());
4355 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4356
4357 mDispatcher->notifyMotion(
4358 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4359 .deviceId(mouseDeviceId)
4360 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4361 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4362 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4363 .build());
4364 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4365
4366 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4367 // already active gesture, it should be sent normally.
4368 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4369 .deviceId(touchDeviceId)
4370 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4371 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4372 .build());
4373 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4374 window->assertNoEvents();
4375}
4376
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004377TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4378 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4379
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004380 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4381 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004382 spyWindow->setFrame(Rect(0, 0, 600, 800));
4383 spyWindow->setTrustedOverlay(true);
4384 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004385 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4386 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004387 window->setFrame(Rect(0, 0, 600, 800));
4388
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004389 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004390 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004391
4392 // Send mouse cursor to the window
4393 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004394 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004395 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4396 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004397 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004398 .build()));
4399
4400 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4401 WithSource(AINPUT_SOURCE_MOUSE)));
4402 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4403 WithSource(AINPUT_SOURCE_MOUSE)));
4404
4405 window->assertNoEvents();
4406 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004407}
4408
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004409TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows_legacy) {
4410 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004411 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4412
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004413 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4414 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004415 spyWindow->setFrame(Rect(0, 0, 600, 800));
4416 spyWindow->setTrustedOverlay(true);
4417 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004418 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4419 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004420 window->setFrame(Rect(0, 0, 600, 800));
4421
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004422 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004423 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004424
4425 // Send mouse cursor to the window
4426 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004427 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004428 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4429 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004430 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004431 .build()));
4432
4433 // Move mouse cursor
4434 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004435 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004436 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4437 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004438 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004439 .build()));
4440
4441 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4442 WithSource(AINPUT_SOURCE_MOUSE)));
4443 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4444 WithSource(AINPUT_SOURCE_MOUSE)));
4445 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4446 WithSource(AINPUT_SOURCE_MOUSE)));
4447 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4448 WithSource(AINPUT_SOURCE_MOUSE)));
4449 // Touch down on the window
4450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004451 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004452 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4453 AINPUT_SOURCE_TOUCHSCREEN)
4454 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004455 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004456 .build()));
4457 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4458 WithSource(AINPUT_SOURCE_MOUSE)));
4459 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4460 WithSource(AINPUT_SOURCE_MOUSE)));
4461 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4462 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4463 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4464 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4465
4466 // pilfer the motion, retaining the gesture on the spy window.
4467 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4468 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4469 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4470
4471 // Touch UP on the window
4472 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004473 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004474 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4475 AINPUT_SOURCE_TOUCHSCREEN)
4476 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004477 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004478 .build()));
4479 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4480 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4481
4482 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4483 // to send a new gesture. It should again go to both windows (spy and the window below), just
4484 // like the first gesture did, before pilfering. The window configuration has not changed.
4485
4486 // One more tap - DOWN
4487 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004488 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004489 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4490 AINPUT_SOURCE_TOUCHSCREEN)
4491 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004492 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004493 .build()));
4494 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4495 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4496 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4497 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4498
4499 // Touch UP on the window
4500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004501 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004502 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4503 AINPUT_SOURCE_TOUCHSCREEN)
4504 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004505 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004506 .build()));
4507 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4508 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4509 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4510 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4511
4512 window->assertNoEvents();
4513 spyWindow->assertNoEvents();
4514}
4515
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004516TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4517 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4518 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4519
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004520 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4521 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004522 spyWindow->setFrame(Rect(0, 0, 600, 800));
4523 spyWindow->setTrustedOverlay(true);
4524 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004525 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4526 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004527 window->setFrame(Rect(0, 0, 600, 800));
4528
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004529 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004530 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4531
4532 // Send mouse cursor to the window
4533 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4534 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4535 .build());
4536
4537 // Move mouse cursor
4538 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4539 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4540 .build());
4541
4542 window->consumeMotionEvent(
4543 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4544 spyWindow->consumeMotionEvent(
4545 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4546 window->consumeMotionEvent(
4547 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4548 spyWindow->consumeMotionEvent(
4549 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4550 // Touch down on the window
4551 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4552 .deviceId(SECOND_DEVICE_ID)
4553 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4554 .build());
4555 window->consumeMotionEvent(
4556 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4557 spyWindow->consumeMotionEvent(
4558 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4559
4560 // pilfer the motion, retaining the gesture on the spy window.
4561 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4562 window->consumeMotionEvent(
4563 AllOf(WithMotionAction(ACTION_CANCEL), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4564 // Mouse hover is not pilfered
4565
4566 // Touch UP on the window
4567 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4568 .deviceId(SECOND_DEVICE_ID)
4569 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4570 .build());
4571 spyWindow->consumeMotionEvent(
4572 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4573
4574 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4575 // to send a new gesture. It should again go to both windows (spy and the window below), just
4576 // like the first gesture did, before pilfering. The window configuration has not changed.
4577
4578 // One more tap - DOWN
4579 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4580 .deviceId(SECOND_DEVICE_ID)
4581 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4582 .build());
4583 window->consumeMotionEvent(
4584 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4585 spyWindow->consumeMotionEvent(
4586 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4587
4588 // Touch UP on the window
4589 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4590 .deviceId(SECOND_DEVICE_ID)
4591 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4592 .build());
4593 window->consumeMotionEvent(
4594 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4595 spyWindow->consumeMotionEvent(
4596 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4597
4598 // Mouse movement continues normally as well
4599 // Move mouse cursor
4600 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4601 .pointer(PointerBuilder(0, ToolType::MOUSE).x(120).y(130))
4602 .build());
4603 window->consumeMotionEvent(
4604 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4605 spyWindow->consumeMotionEvent(
4606 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4607
4608 window->assertNoEvents();
4609 spyWindow->assertNoEvents();
4610}
4611
Garfield Tandf26e862020-07-01 20:18:19 -07004612// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4613// directly in this test.
4614TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004615 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004616 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4617 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004618 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004619
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004620 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004621
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004622 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004623
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004625 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004626 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4627 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004628 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004629 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004630 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004631 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004633 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004634 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4635 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004636 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004637 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004638 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4639 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004640
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004642 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004643 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4644 AINPUT_SOURCE_MOUSE)
4645 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4646 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004647 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004648 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004649 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004650
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004652 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004653 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4654 AINPUT_SOURCE_MOUSE)
4655 .buttonState(0)
4656 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004657 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004658 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004659 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004660
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004661 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004662 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004663 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4664 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004665 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004666 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004667 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004668
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004669 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4670 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4671 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004672 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004673 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4674 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004675 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004676 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004677 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004678}
4679
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004680/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004681 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4682 * is generated.
4683 */
4684TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4685 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004686 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4687 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004688 window->setFrame(Rect(0, 0, 1200, 800));
4689
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004690 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004691
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004692 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004693
4694 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004695 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004696 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4697 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004698 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004699 .build()));
4700 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4701
4702 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004703 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004704 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4705}
4706
4707/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004708 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4709 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004710TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4711 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4712 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004713 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004714 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4715 ui::LogicalDisplayId::DEFAULT);
Daniel Norman7487dfa2023-08-02 16:39:45 -07004716 window->setFrame(Rect(0, 0, 1200, 800));
4717
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004718 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Daniel Norman7487dfa2023-08-02 16:39:45 -07004719
4720 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4721
4722 MotionEventBuilder hoverEnterBuilder =
4723 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4724 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4725 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4727 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4728 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4729 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4730 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4731 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4732}
4733
4734/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004735 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4736 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004737TEST_F(InputDispatcherTest, TouchDownAfterMouseHover_legacy) {
4738 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004739 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004740 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4741 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004742 window->setFrame(Rect(0, 0, 100, 100));
4743
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004744 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004745
4746 const int32_t mouseDeviceId = 7;
4747 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004748
4749 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004750 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4751 .deviceId(mouseDeviceId)
4752 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4753 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004754 window->consumeMotionEvent(
4755 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4756
4757 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004758 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4759 .deviceId(touchDeviceId)
4760 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4761 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004762
4763 window->consumeMotionEvent(
4764 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4765 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4766}
4767
4768/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004769 * If mouse is hovering when the touch goes down, the hovering should not be stopped.
4770 */
4771TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4772 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4773 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004774 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4775 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004776 window->setFrame(Rect(0, 0, 100, 100));
4777
4778 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4779
4780 const int32_t mouseDeviceId = 7;
4781 const int32_t touchDeviceId = 4;
4782
4783 // Start hovering with the mouse
4784 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4785 .deviceId(mouseDeviceId)
4786 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4787 .build());
4788 window->consumeMotionEvent(
4789 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4790
4791 // Touch goes down
4792 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4793 .deviceId(touchDeviceId)
4794 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4795 .build());
4796 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4797}
4798
4799/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004800 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004801 * The tap causes a HOVER_EXIT event to be generated because the current event
4802 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004803 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004804TEST_F(InputDispatcherTest, MouseHoverAndTouchTap_legacy) {
4805 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004806 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004807 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4808 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004809 window->setFrame(Rect(0, 0, 100, 100));
4810
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004811 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004812 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4813 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4814 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004815 ASSERT_NO_FATAL_FAILURE(
4816 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4817 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004818
4819 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4821 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4822 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004823 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004824 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4825 WithSource(AINPUT_SOURCE_MOUSE))));
4826
4827 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004828 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4829 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4830
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004831 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4832 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4833 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004834 ASSERT_NO_FATAL_FAILURE(
4835 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4836 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4837}
4838
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004839/**
4840 * Send a mouse hover event followed by a tap from touchscreen.
4841 * The tap causes a HOVER_EXIT event to be generated because the current event
4842 * stream's source has been switched.
4843 */
4844TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4845 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4846 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004847 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4848 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004849 window->setFrame(Rect(0, 0, 100, 100));
4850
4851 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4852 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4853 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4854 .build());
4855
4856 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4857 WithSource(AINPUT_SOURCE_MOUSE)));
4858
4859 // Tap on the window
4860 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4861 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4862 .build());
4863
4864 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4865 WithSource(AINPUT_SOURCE_MOUSE)));
4866
4867 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4868 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4869
4870 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4871 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4872 .build());
4873
4874 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4875 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4876}
4877
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004878TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4879 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4880 sp<FakeWindowHandle> windowDefaultDisplay =
4881 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004882 ui::LogicalDisplayId::DEFAULT);
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004883 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4884 sp<FakeWindowHandle> windowSecondDisplay =
4885 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4886 SECOND_DISPLAY_ID);
4887 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4888
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004889 mDispatcher->onWindowInfosChanged(
4890 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004891
4892 // Set cursor position in window in default display and check that hover enter and move
4893 // events are generated.
4894 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004895 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004896 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4897 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004898 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004899 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004900 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004901 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004902
4903 // Remove all windows in secondary display and check that no event happens on window in
4904 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004905 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
4906
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004907 windowDefaultDisplay->assertNoEvents();
4908
4909 // Move cursor position in window in default display and check that only hover move
4910 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004911 mDispatcher->onWindowInfosChanged(
4912 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004913 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004914 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004915 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4916 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004917 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004918 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004919 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004920 windowDefaultDisplay->consumeMotionEvent(
4921 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4922 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004923 windowDefaultDisplay->assertNoEvents();
4924}
4925
Garfield Tan00f511d2019-06-12 16:55:40 -07004926TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07004927 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07004928
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004929 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4930 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004931 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004932 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4933 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004934 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07004935
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004936 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tan00f511d2019-06-12 16:55:40 -07004937
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004938 mDispatcher->onWindowInfosChanged(
4939 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07004940
4941 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
4942 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004943 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004944 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004945 ui::LogicalDisplayId::DEFAULT, {610, 400}, {599, 400}));
4946 windowLeft->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07004947 windowRight->assertNoEvents();
4948}
4949
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004950TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004951 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004952 sp<FakeWindowHandle> window =
4953 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
4954 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07004955 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004956
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004957 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07004958 setFocusedWindow(window);
4959
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01004960 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004961
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004962 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004963
4964 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004965 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004966
4967 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
4968 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004969 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004970 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004971}
4972
4973TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07004974 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004975 sp<FakeWindowHandle> window =
4976 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
4977 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004978
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004979 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004980
Prabir Pradhan678438e2023-04-13 19:32:51 +00004981 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004982 AINPUT_SOURCE_TOUCHSCREEN,
4983 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004984
4985 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004986 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004987
4988 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
4989 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004990 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08004991 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004992 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08004993}
4994
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07004995TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
4996 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004997 sp<FakeWindowHandle> window =
4998 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
4999 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005000
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005001 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005002
5003 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5004 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
5005 .build());
5006
5007 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5008
5009 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
5010 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
5011 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5012
5013 // After the device has been reset, a new hovering stream can be sent to the window
5014 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5015 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
5016 .build());
5017 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5018}
5019
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005020TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
5021 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005022 sp<FakeWindowHandle> window =
5023 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5024 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005025 window->setFocusable(true);
5026
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005027 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005028 setFocusedWindow(window);
5029
5030 window->consumeFocusEvent(true);
5031
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005032 const NotifyKeyArgs keyArgs =
5033 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005034 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
5035 const nsecs_t injectTime = keyArgs.eventTime;
5036 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005037 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005038 // The dispatching time should be always greater than or equal to intercept key timeout.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005039 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005040 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
5041 std::chrono::nanoseconds(interceptKeyTimeout).count());
5042}
5043
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005044/**
5045 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
5046 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005047TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
5048 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005049 sp<FakeWindowHandle> window =
5050 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5051 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005052 window->setFocusable(true);
5053
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005054 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005055 setFocusedWindow(window);
5056
5057 window->consumeFocusEvent(true);
5058
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005059 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
5060 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005061
5062 // Set a value that's significantly larger than the default consumption timeout. If the
5063 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
5064 mFakePolicy->setInterceptKeyTimeout(600ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005065 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005066 // Window should receive key event immediately when same key up.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005067 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005068}
5069
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005070/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005071 * Two windows. First is a regular window. Second does not overlap with the first, and has
5072 * WATCH_OUTSIDE_TOUCH.
5073 * Both windows are owned by the same UID.
5074 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
5075 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
5076 */
5077TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
5078 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005079 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5080 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005081 window->setFrame(Rect{0, 0, 100, 100});
5082
5083 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005084 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005085 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005086 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5087 outsideWindow->setWatchOutsideTouch(true);
5088 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005089 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005090
5091 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005092 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005093 AINPUT_SOURCE_TOUCHSCREEN,
5094 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005095 window->consumeMotionDown();
5096 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
5097 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
5098 outsideWindow->consumeMotionEvent(
5099 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005100
5101 // Ensure outsideWindow doesn't get any more events for the gesture.
5102 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005103 ui::LogicalDisplayId::DEFAULT, {PointF{51, 51}}));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005104 window->consumeMotionMove();
5105 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005106}
5107
5108/**
Linnan Liccf6ce32024-04-11 20:32:13 +08005109 * Three windows:
5110 * - Left window
5111 * - Right window
5112 * - Outside window(watch for ACTION_OUTSIDE events)
5113 * The windows "left" and "outside" share the same owner, the window "right" has a different owner,
5114 * In order to allow the outside window can receive the ACTION_OUTSIDE events, the outside window is
5115 * positioned above the "left" and "right" windows, and it doesn't overlap with them.
5116 *
5117 * First, device A report a down event landed in the right window, the outside window can receive
5118 * an ACTION_OUTSIDE event that with zeroed coordinates, the device B report a down event landed
5119 * in the left window, the outside window can receive an ACTION_OUTSIDE event the with valid
5120 * coordinates, after these, device A and device B continue report MOVE event, the right and left
5121 * window can receive it, but outside window event can't receive it.
5122 */
5123TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinatesWhenMultiDevice) {
5124 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5125 sp<FakeWindowHandle> leftWindow =
5126 sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005127 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005128 leftWindow->setFrame(Rect{0, 0, 100, 100});
5129 leftWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5130
5131 sp<FakeWindowHandle> outsideWindow =
5132 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005133 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005134 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5135 outsideWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5136 outsideWindow->setWatchOutsideTouch(true);
5137
5138 std::shared_ptr<FakeApplicationHandle> anotherApplication =
5139 std::make_shared<FakeApplicationHandle>();
5140 sp<FakeWindowHandle> rightWindow =
5141 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Right Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005142 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005143 rightWindow->setFrame(Rect{100, 0, 200, 100});
5144 rightWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
5145
5146 // OutsideWindow must be above left window and right window to receive ACTION_OUTSIDE events
5147 // when left window or right window is tapped
5148 mDispatcher->onWindowInfosChanged(
5149 {{*outsideWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()},
5150 {},
5151 0,
5152 0});
5153
5154 const DeviceId deviceA = 9;
5155 const DeviceId deviceB = 3;
5156
5157 // Tap on right window use device A
5158 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5159 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5160 .deviceId(deviceA)
5161 .build());
5162 leftWindow->assertNoEvents();
5163 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5164 // Right window is belonged to another owner, so outsideWindow should receive ACTION_OUTSIDE
5165 // with zeroed coords.
5166 outsideWindow->consumeMotionEvent(
5167 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceA), WithCoords(0, 0)));
5168
5169 // Tap on left window use device B
5170 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5171 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5172 .deviceId(deviceB)
5173 .build());
5174 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5175 rightWindow->assertNoEvents();
5176 // Because new gesture down on the left window that has the same owner with outside Window, the
5177 // outside Window should receive the ACTION_OUTSIDE with coords.
5178 outsideWindow->consumeMotionEvent(
5179 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceB), WithCoords(-50, -50)));
5180
5181 // Ensure that windows that can only accept outside do not receive remaining gestures
5182 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5183 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
5184 .deviceId(deviceA)
5185 .build());
5186 leftWindow->assertNoEvents();
5187 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA)));
5188
5189 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5190 .pointer(PointerBuilder(0, ToolType::FINGER).x(51).y(51))
5191 .deviceId(deviceB)
5192 .build());
5193 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
5194 rightWindow->assertNoEvents();
5195 outsideWindow->assertNoEvents();
5196}
5197
5198/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005199 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
5200 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
5201 * ACTION_OUTSIDE event is sent per gesture.
5202 */
5203TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
5204 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
5205 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005206 sp<FakeWindowHandle> window =
5207 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5208 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005209 window->setWatchOutsideTouch(true);
5210 window->setFrame(Rect{0, 0, 100, 100});
5211 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005212 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005213 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005214 secondWindow->setFrame(Rect{100, 100, 200, 200});
5215 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005216 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005217 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005218 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005219 mDispatcher->onWindowInfosChanged(
5220 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005221
5222 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005223 mDispatcher->notifyMotion(
5224 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5225 ui::LogicalDisplayId::DEFAULT, {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005226 window->assertNoEvents();
5227 secondWindow->assertNoEvents();
5228
5229 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
5230 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005231 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005232 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005233 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005234 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
5235 window->consumeMotionEvent(
5236 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005237 secondWindow->consumeMotionDown();
5238 thirdWindow->assertNoEvents();
5239
5240 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
5241 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005242 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005243 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5244 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005245 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005246 window->assertNoEvents();
5247 secondWindow->consumeMotionMove();
5248 thirdWindow->consumeMotionDown();
5249}
5250
Prabir Pradhan814fe082022-07-22 20:22:18 +00005251TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
5252 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005253 sp<FakeWindowHandle> window =
5254 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5255 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005256 window->setFocusable(true);
5257
Patrick Williamsd828f302023-04-28 17:52:08 -05005258 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005259 setFocusedWindow(window);
5260
5261 window->consumeFocusEvent(true);
5262
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005263 const NotifyKeyArgs keyDown =
5264 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
5265 const NotifyKeyArgs keyUp =
5266 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005267 mDispatcher->notifyKey(keyDown);
5268 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005269
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005270 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5271 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005272
5273 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05005274 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005275
5276 window->consumeFocusEvent(false);
5277
Prabir Pradhan678438e2023-04-13 19:32:51 +00005278 mDispatcher->notifyKey(keyDown);
5279 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005280 window->assertNoEvents();
5281}
5282
Arthur Hung96483742022-11-15 03:30:48 +00005283TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
5284 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005285 sp<FakeWindowHandle> window =
5286 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5287 ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005288 // Ensure window is non-split and have some transform.
5289 window->setPreventSplitting(true);
5290 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05005291 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00005292
5293 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005294 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5295 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung96483742022-11-15 03:30:48 +00005296 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005297 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005298
5299 const MotionEvent secondFingerDownEvent =
5300 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005301 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung96483742022-11-15 03:30:48 +00005302 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005303 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5304 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00005305 .build();
5306 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005307 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00005308 InputEventInjectionSync::WAIT_FOR_RESULT))
5309 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5310
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005311 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
5312 ASSERT_NE(nullptr, event);
5313 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
5314 EXPECT_EQ(70, event->getX(0)); // 50 + 20
5315 EXPECT_EQ(90, event->getY(0)); // 50 + 40
5316 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
5317 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00005318}
5319
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005320/**
5321 * Two windows: a splittable and a non-splittable.
5322 * The non-splittable window shouldn't receive any "incomplete" gestures.
5323 * Send the first pointer to the splittable window, and then touch the non-splittable window.
5324 * The second pointer should be dropped because the initial window is splittable, so it won't get
5325 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
5326 * "incomplete" gestures.
5327 */
5328TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
5329 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5330 sp<FakeWindowHandle> leftWindow =
5331 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005332 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005333 leftWindow->setPreventSplitting(false);
5334 leftWindow->setFrame(Rect(0, 0, 100, 100));
5335 sp<FakeWindowHandle> rightWindow =
5336 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005337 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005338 rightWindow->setPreventSplitting(true);
5339 rightWindow->setFrame(Rect(100, 100, 200, 200));
5340 mDispatcher->onWindowInfosChanged(
5341 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5342
5343 // Touch down on left, splittable window
5344 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5345 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5346 .build());
5347 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5348
5349 mDispatcher->notifyMotion(
5350 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5351 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5352 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
5353 .build());
5354 leftWindow->assertNoEvents();
5355 rightWindow->assertNoEvents();
5356}
5357
Harry Cuttsb166c002023-05-09 13:06:05 +00005358TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
5359 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005360 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5361 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005362 window->setFrame(Rect(0, 0, 400, 400));
5363 sp<FakeWindowHandle> trustedOverlay =
5364 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005365 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005366 trustedOverlay->setSpy(true);
5367 trustedOverlay->setTrustedOverlay(true);
5368
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005369 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005370
5371 // Start a three-finger touchpad swipe
5372 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5373 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5374 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5375 .build());
5376 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5377 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5378 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5379 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5380 .build());
5381 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5382 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5383 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5384 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5385 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5386 .build());
5387
5388 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5389 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5390 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
5391
5392 // Move the swipe a bit
5393 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5394 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5395 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5396 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5397 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5398 .build());
5399
5400 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5401
5402 // End the swipe
5403 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5404 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5405 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5406 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5407 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5408 .build());
5409 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5410 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5411 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5412 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5413 .build());
5414 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5415 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5416 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5417 .build());
5418
5419 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
5420 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5421 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
5422
5423 window->assertNoEvents();
5424}
5425
5426TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
5427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005428 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5429 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005430 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005431 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005432
5433 // Start a three-finger touchpad swipe
5434 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5435 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5436 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5437 .build());
5438 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5439 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5440 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5441 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5442 .build());
5443 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5444 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5445 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5446 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5447 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5448 .build());
5449
5450 // Move the swipe a bit
5451 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5452 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5453 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5454 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5455 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5456 .build());
5457
5458 // End the swipe
5459 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5460 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5461 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5462 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5463 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5464 .build());
5465 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5466 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5467 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5468 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5469 .build());
5470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5471 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5472 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5473 .build());
5474
5475 window->assertNoEvents();
5476}
5477
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005478/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005479 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
5480 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005481 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005482 */
5483TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
5484 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005485 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5486 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005487 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005488 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005489
5490 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
5491 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5492 .downTime(baseTime + 10)
5493 .eventTime(baseTime + 10)
5494 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5495 .build());
5496
5497 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5498
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005499 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005500 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005501
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005502 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005503
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005504 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5505 .downTime(baseTime + 10)
5506 .eventTime(baseTime + 30)
5507 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5508 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5509 .build());
5510
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005511 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5512
5513 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005514 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5515 .downTime(baseTime + 10)
5516 .eventTime(baseTime + 40)
5517 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5518 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5519 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005520
5521 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5522
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005523 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5524 .downTime(baseTime + 10)
5525 .eventTime(baseTime + 50)
5526 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5527 .build());
5528
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005529 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
5530
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005531 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5532 .downTime(baseTime + 60)
5533 .eventTime(baseTime + 60)
5534 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
5535 .build());
5536
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005537 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005538}
5539
5540/**
Hu Guo771a7692023-09-17 20:51:08 +08005541 * When there are multiple screens, such as screen projection to TV or screen recording, if the
5542 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
5543 * its coordinates should be converted by the transform of the windows of target screen.
5544 */
5545TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
5546 // This case will create a window and a spy window on the default display and mirror
5547 // window on the second display. cancel event is sent through spy window pilferPointers
5548 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5549
5550 sp<FakeWindowHandle> spyWindowDefaultDisplay =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005551 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
5552 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005553 spyWindowDefaultDisplay->setTrustedOverlay(true);
5554 spyWindowDefaultDisplay->setSpy(true);
5555
5556 sp<FakeWindowHandle> windowDefaultDisplay =
5557 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005558 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005559 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
5560
5561 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
5562 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
5563
5564 // Add the windows to the dispatcher
5565 mDispatcher->onWindowInfosChanged(
5566 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
5567 *windowSecondDisplay->getInfo()},
5568 {},
5569 0,
5570 0});
5571
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005572 // Send down to ui::LogicalDisplayId::DEFAULT
Hu Guo771a7692023-09-17 20:51:08 +08005573 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005574 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5575 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Hu Guo771a7692023-09-17 20:51:08 +08005576 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5577
5578 spyWindowDefaultDisplay->consumeMotionDown();
5579 windowDefaultDisplay->consumeMotionDown();
5580
5581 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
5582
5583 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005584 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
5585 ASSERT_NE(nullptr, event);
5586 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08005587
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005588 // The cancel event is sent to windowDefaultDisplay of the ui::LogicalDisplayId::DEFAULT
5589 // display, so the coordinates of the cancel are converted by windowDefaultDisplay's transform,
5590 // the x and y coordinates are both 100, otherwise if the cancel event is sent to
5591 // windowSecondDisplay of SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005592 EXPECT_EQ(100, event->getX(0));
5593 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08005594}
5595
5596/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005597 * Ensure the correct coordinate spaces are used by InputDispatcher.
5598 *
5599 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5600 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5601 * space.
5602 */
5603class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5604public:
5605 void SetUp() override {
5606 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005607 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005608 }
5609
Linnan Li13bf76a2024-05-05 19:18:02 +08005610 void addDisplayInfo(ui::LogicalDisplayId displayId, const ui::Transform& transform) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005611 gui::DisplayInfo info;
5612 info.displayId = displayId;
5613 info.transform = transform;
5614 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005615 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005616 }
5617
5618 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5619 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005620 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005621 }
5622
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005623 void removeAllWindowsAndDisplays() {
5624 mDisplayInfos.clear();
5625 mWindowInfos.clear();
5626 }
5627
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005628 // Set up a test scenario where the display has a scaled projection and there are two windows
5629 // on the display.
5630 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5631 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5632 // respectively.
5633 ui::Transform displayTransform;
5634 displayTransform.set(2, 0, 0, 4);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005635 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005636
5637 std::shared_ptr<FakeApplicationHandle> application =
5638 std::make_shared<FakeApplicationHandle>();
5639
5640 // Add two windows to the display. Their frames are represented in the display space.
5641 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005642 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005643 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005644 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5645 addWindow(firstWindow);
5646
5647 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005648 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005649 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005650 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5651 addWindow(secondWindow);
5652 return {std::move(firstWindow), std::move(secondWindow)};
5653 }
5654
5655private:
5656 std::vector<gui::DisplayInfo> mDisplayInfos;
5657 std::vector<gui::WindowInfo> mWindowInfos;
5658};
5659
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005660TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005661 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5662 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005663 // selected so that if the hit test was performed with the point and the bounds being in
5664 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005665 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005666 AINPUT_SOURCE_TOUCHSCREEN,
5667 ui::LogicalDisplayId::DEFAULT, {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005668
5669 firstWindow->consumeMotionDown();
5670 secondWindow->assertNoEvents();
5671}
5672
5673// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5674// the event should be treated as being in the logical display space.
5675TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5676 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5677 // Send down to the first window. The point is represented in the logical display space. The
5678 // point is selected so that if the hit test was done in logical display space, then it would
5679 // end up in the incorrect window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005680 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005681 PointF{75 * 2, 55 * 4});
5682
5683 firstWindow->consumeMotionDown();
5684 secondWindow->assertNoEvents();
5685}
5686
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005687// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5688// event should be treated as being in the logical display space.
5689TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5690 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5691
5692 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5693 ui::Transform injectedEventTransform;
5694 injectedEventTransform.set(matrix);
5695 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5696 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5697
5698 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005699 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005700 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005701 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005702 .x(untransformedPoint.x)
5703 .y(untransformedPoint.y))
5704 .build();
5705 event.transform(matrix);
5706
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005707 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005708 InputEventInjectionSync::WAIT_FOR_RESULT);
5709
5710 firstWindow->consumeMotionDown();
5711 secondWindow->assertNoEvents();
5712}
5713
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005714TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5715 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5716
5717 // Send down to the second window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005718 mDispatcher->notifyMotion(
5719 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5720 ui::LogicalDisplayId::DEFAULT, {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005721
5722 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005723 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5724 ASSERT_NE(nullptr, event);
5725 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005726
5727 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005728 EXPECT_EQ(300, event->getRawX(0));
5729 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005730
5731 // Ensure that the x and y values are in the window's coordinate space.
5732 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5733 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005734 EXPECT_EQ(100, event->getX(0));
5735 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005736}
5737
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005738TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5739 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5740 // The monitor will always receive events in the logical display's coordinate space, because
5741 // it does not have a window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005742 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ui::LogicalDisplayId::DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005743
5744 // Send down to the first window.
5745 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005746 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005747 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5748 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5749
5750 // Second pointer goes down on second window.
5751 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005752 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005753 {PointF{50, 100}, PointF{150, 220}}));
5754 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5755 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5756 {1, PointF{300, 880}}};
5757 monitor.consumeMotionEvent(
5758 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5759
5760 mDispatcher->cancelCurrentTouch();
5761
5762 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5763 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5764 monitor.consumeMotionEvent(
5765 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5766}
5767
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005768TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5769 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5770
5771 // Send down to the first window.
5772 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005773 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005774 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5775
5776 // The pointer is transferred to the second window, and the second window receives it in the
5777 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005778 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005779 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5780 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5781}
5782
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005783TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5784 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5785
5786 // Send hover move to the second window, and ensure it shows up as hover enter.
5787 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005788 ui::LogicalDisplayId::DEFAULT,
5789 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005790 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5791 WithCoords(100, 80), WithRawCoords(300, 880)));
5792
5793 // Touch down at the same location and ensure a hover exit is synthesized.
5794 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005795 ui::LogicalDisplayId::DEFAULT,
5796 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005797 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5798 WithRawCoords(300, 880)));
5799 secondWindow->consumeMotionEvent(
5800 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5801 secondWindow->assertNoEvents();
5802 firstWindow->assertNoEvents();
5803}
5804
Prabir Pradhan453ae732023-10-13 14:30:14 +00005805// Same as above, but while the window is being mirrored.
5806TEST_F(InputDispatcherDisplayProjectionTest,
5807 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5808 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5809
5810 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5811 ui::Transform secondDisplayTransform;
5812 secondDisplayTransform.set(matrix);
5813 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5814
5815 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5816 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5817 addWindow(secondWindowClone);
5818
5819 // Send hover move to the second window, and ensure it shows up as hover enter.
5820 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005821 ui::LogicalDisplayId::DEFAULT,
5822 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00005823 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5824 WithCoords(100, 80), WithRawCoords(300, 880)));
5825
5826 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5827 // display.
5828 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005829 ui::LogicalDisplayId::DEFAULT,
5830 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00005831 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5832 WithRawCoords(300, 880)));
5833 secondWindow->consumeMotionEvent(
5834 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5835 secondWindow->assertNoEvents();
5836 firstWindow->assertNoEvents();
5837}
5838
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005839TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
5840 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5841
5842 // Send hover enter to second window
5843 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005844 ui::LogicalDisplayId::DEFAULT,
5845 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005846 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5847 WithCoords(100, 80), WithRawCoords(300, 880)));
5848
5849 mDispatcher->cancelCurrentTouch();
5850
5851 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5852 WithRawCoords(300, 880)));
5853 secondWindow->assertNoEvents();
5854 firstWindow->assertNoEvents();
5855}
5856
Prabir Pradhan453ae732023-10-13 14:30:14 +00005857// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00005858TEST_F(InputDispatcherDisplayProjectionTest,
5859 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
5860 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5861
5862 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5863 ui::Transform secondDisplayTransform;
5864 secondDisplayTransform.set(matrix);
5865 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5866
5867 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5868 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5869 addWindow(secondWindowClone);
5870
5871 // Send hover enter to second window
5872 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005873 ui::LogicalDisplayId::DEFAULT,
5874 {PointF{150, 220}}));
Prabir Pradhan16463382023-10-12 23:03:19 +00005875 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5876 WithCoords(100, 80), WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005877 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00005878
5879 mDispatcher->cancelCurrentTouch();
5880
5881 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
5882 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5883 WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005884 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00005885 secondWindow->assertNoEvents();
5886 firstWindow->assertNoEvents();
5887}
5888
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005889/** Ensure consistent behavior of InputDispatcher in all orientations. */
5890class InputDispatcherDisplayOrientationFixture
5891 : public InputDispatcherDisplayProjectionTest,
5892 public ::testing::WithParamInterface<ui::Rotation> {};
5893
5894// This test verifies the touchable region of a window for all rotations of the display by tapping
5895// in different locations on the display, specifically points close to the four corners of a
5896// window.
5897TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
5898 constexpr static int32_t displayWidth = 400;
5899 constexpr static int32_t displayHeight = 800;
5900
5901 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5902
5903 const auto rotation = GetParam();
5904
5905 // Set up the display with the specified rotation.
5906 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5907 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5908 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5909 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5910 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005911 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005912
5913 // Create a window with its bounds determined in the logical display.
5914 const Rect frameInLogicalDisplay(100, 100, 200, 300);
5915 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005916 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5917 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005918 window->setFrame(frameInDisplay, displayTransform);
5919 addWindow(window);
5920
5921 // The following points in logical display space should be inside the window.
5922 static const std::array<vec2, 4> insidePoints{
5923 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
5924 for (const auto pointInsideWindow : insidePoints) {
5925 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
5926 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005927 mDispatcher->notifyMotion(
5928 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5929 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005930 window->consumeMotionDown();
5931
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005932 mDispatcher->notifyMotion(
5933 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5934 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005935 window->consumeMotionUp();
5936 }
5937
5938 // The following points in logical display space should be outside the window.
5939 static const std::array<vec2, 5> outsidePoints{
5940 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
5941 for (const auto pointOutsideWindow : outsidePoints) {
5942 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
5943 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005944 mDispatcher->notifyMotion(
5945 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5946 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005947
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005948 mDispatcher->notifyMotion(
5949 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
5950 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005951 }
5952 window->assertNoEvents();
5953}
5954
Linnan Li5e5645e2024-03-05 14:43:05 +00005955// This test verifies the occlusion detection for all rotations of the display by tapping
5956// in different locations on the display, specifically points close to the four corners of a
5957// window.
5958TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) {
5959 constexpr static int32_t displayWidth = 400;
5960 constexpr static int32_t displayHeight = 800;
5961
5962 std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication =
5963 std::make_shared<FakeApplicationHandle>();
5964 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5965
5966 const auto rotation = GetParam();
5967
5968 // Set up the display with the specified rotation.
5969 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
5970 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
5971 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
5972 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
5973 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005974 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Linnan Li5e5645e2024-03-05 14:43:05 +00005975
5976 // Create a window that not trusted.
5977 const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
5978
5979 const Rect untrustedWindowFrameInDisplay =
5980 displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay);
5981
5982 sp<FakeWindowHandle> untrustedWindow =
5983 sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005984 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00005985 untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
5986 untrustedWindow->setTrustedOverlay(false);
5987 untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
5988 untrustedWindow->setTouchable(false);
5989 untrustedWindow->setAlpha(1.0f);
5990 untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5991 addWindow(untrustedWindow);
5992
5993 // Create a simple app window below the untrusted window.
5994 const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600);
5995 const Rect simpleAppWindowFrameInDisplay =
5996 displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay);
5997
5998 sp<FakeWindowHandle> simpleAppWindow =
5999 sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006000 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006001 simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
6002 simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
6003 addWindow(simpleAppWindow);
6004
6005 // The following points in logical display space should be inside the untrusted window, so
6006 // the simple window could not receive events that coordinate is these point.
6007 static const std::array<vec2, 4> untrustedPoints{
6008 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6009
6010 for (const auto untrustedPoint : untrustedPoints) {
6011 const vec2 p = displayTransform.inverse().transform(untrustedPoint);
6012 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006013 mDispatcher->notifyMotion(
6014 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6015 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6016 mDispatcher->notifyMotion(
6017 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6018 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Linnan Li5e5645e2024-03-05 14:43:05 +00006019 }
6020 untrustedWindow->assertNoEvents();
6021 simpleAppWindow->assertNoEvents();
6022 // The following points in logical display space should be outside the untrusted window, so
6023 // the simple window should receive events that coordinate is these point.
6024 static const std::array<vec2, 5> trustedPoints{
6025 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6026 for (const auto trustedPoint : trustedPoints) {
6027 const vec2 p = displayTransform.inverse().transform(trustedPoint);
6028 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006029 mDispatcher->notifyMotion(
6030 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6031 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6032 simpleAppWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006033 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006034 mDispatcher->notifyMotion(
6035 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6036 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6037 simpleAppWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006038 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6039 }
6040 untrustedWindow->assertNoEvents();
6041}
6042
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006043// Run the precision tests for all rotations.
6044INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
6045 InputDispatcherDisplayOrientationFixture,
6046 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6047 ui::ROTATION_270),
6048 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6049 return ftl::enum_string(testParamInfo.param);
6050 });
6051
Siarhei Vishniakou18050092021-09-01 13:32:49 -07006052using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
6053 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006054
6055class TransferTouchFixture : public InputDispatcherTest,
6056 public ::testing::WithParamInterface<TransferFunction> {};
6057
6058TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07006059 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006060
6061 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006062 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006063 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006064 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006065 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006066 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006067 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006068 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006069 sp<FakeWindowHandle> wallpaper =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006070 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
6071 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006072 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006073 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006074 mDispatcher->onWindowInfosChanged(
6075 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00006076 setFocusedWindow(firstWindow);
6077 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006078
6079 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006080 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006081 AINPUT_SOURCE_TOUCHSCREEN,
6082 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006083
Svet Ganov5d3bc372020-01-26 23:11:07 -08006084 // Only the first window should get the down event
6085 firstWindow->consumeMotionDown();
6086 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006087 wallpaper->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006088 // Dispatcher reports pointer down outside focus for the wallpaper
6089 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006090
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006091 // Transfer touch to the second window
6092 TransferFunction f = GetParam();
6093 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6094 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006095 // The first window gets cancel and the second gets down
6096 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006097 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6098 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6099 wallpaper->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006100 // There should not be any changes to the focused window when transferring touch
6101 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006102
6103 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006104 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006105 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00006106 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08006107 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006108 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6109 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006110 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006111}
6112
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006113/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00006114 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
6115 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
6116 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006117 * natural to the user.
6118 * In this test, we are sending a pointer to both spy window and first window. We then try to
6119 * transfer touch to the second window. The dispatcher should identify the first window as the
6120 * one that should lose the gesture, and therefore the action should be to move the gesture from
6121 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006122 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
6123 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006124 */
6125TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
6126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6127
6128 // Create a couple of windows + a spy window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006129 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6130 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006131 spyWindow->setTrustedOverlay(true);
6132 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006133 sp<FakeWindowHandle> firstWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "First",
6134 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006135 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006136 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
6137 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006138
6139 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006140 mDispatcher->onWindowInfosChanged(
6141 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006142
6143 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006144 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006145 AINPUT_SOURCE_TOUCHSCREEN,
6146 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006147 // Only the first window and spy should get the down event
6148 spyWindow->consumeMotionDown();
6149 firstWindow->consumeMotionDown();
6150
6151 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00006152 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006153 TransferFunction f = GetParam();
6154 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6155 ASSERT_TRUE(success);
6156 // The first window gets cancel and the second gets down
6157 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006158 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6159 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006160
6161 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006162 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006163 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006164 // The first window gets no events and the second+spy get up
6165 firstWindow->assertNoEvents();
6166 spyWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006167 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6168 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006169}
6170
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006171TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006172 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006173
6174 PointF touchPoint = {10, 10};
6175
6176 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006177 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006178 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006179 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006180 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006181 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006182 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006183 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006184 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006185
6186 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006187 mDispatcher->onWindowInfosChanged(
6188 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006189
6190 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006191 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006192 AINPUT_SOURCE_TOUCHSCREEN,
6193 ui::LogicalDisplayId::DEFAULT, {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006194 // Only the first window should get the down event
6195 firstWindow->consumeMotionDown();
6196 secondWindow->assertNoEvents();
6197
6198 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006199 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006200 ui::LogicalDisplayId::DEFAULT,
6201 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006202 // Only the first window should get the pointer down event
6203 firstWindow->consumeMotionPointerDown(1);
6204 secondWindow->assertNoEvents();
6205
6206 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006207 TransferFunction f = GetParam();
6208 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6209 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006210 // The first window gets cancel and the second gets down and pointer down
6211 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006212 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6213 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6214 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006215 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006216
6217 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006218 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006219 ui::LogicalDisplayId::DEFAULT,
6220 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006221 // The first window gets nothing and the second gets pointer up
6222 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006223 secondWindow->consumeMotionPointerUp(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006224 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006225
6226 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006227 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006228 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006229 // The first window gets nothing and the second gets up
6230 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006231 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6232 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006233}
6234
Arthur Hungc539dbb2022-12-08 07:45:36 +00006235TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
6236 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6237
6238 // Create a couple of windows
6239 sp<FakeWindowHandle> firstWindow =
6240 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006241 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006242 firstWindow->setDupTouchToWallpaper(true);
6243 sp<FakeWindowHandle> secondWindow =
6244 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006245 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006246 secondWindow->setDupTouchToWallpaper(true);
6247
6248 sp<FakeWindowHandle> wallpaper1 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006249 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1",
6250 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006251 wallpaper1->setIsWallpaper(true);
6252
6253 sp<FakeWindowHandle> wallpaper2 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006254 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2",
6255 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006256 wallpaper2->setIsWallpaper(true);
6257 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006258 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
6259 *secondWindow->getInfo(), *wallpaper2->getInfo()},
6260 {},
6261 0,
6262 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00006263
6264 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006265 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006266 AINPUT_SOURCE_TOUCHSCREEN,
6267 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006268
6269 // Only the first window should get the down event
6270 firstWindow->consumeMotionDown();
6271 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006272 wallpaper1->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006273 wallpaper2->assertNoEvents();
6274
6275 // Transfer touch focus to the second window
6276 TransferFunction f = GetParam();
6277 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6278 ASSERT_TRUE(success);
6279
6280 // The first window gets cancel and the second gets down
6281 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006282 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6283 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6284 wallpaper1->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
6285 wallpaper2->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006286 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006287
6288 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006289 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006290 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006291 // The first window gets no events and the second gets up
6292 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006293 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6294 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006295 wallpaper1->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006296 wallpaper2->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006297 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006298}
6299
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006300// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00006301// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006302// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006303INSTANTIATE_TEST_SUITE_P(
6304 InputDispatcherTransferFunctionTests, TransferTouchFixture,
6305 ::testing::Values(
6306 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
6307 sp<IBinder> destChannelToken) {
6308 return dispatcher->transferTouchOnDisplay(destChannelToken,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006309 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006310 },
6311 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
6312 sp<IBinder> to) {
6313 return dispatcher->transferTouchGesture(from, to,
6314 /*isDragAndDrop=*/false);
6315 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006316
Prabir Pradhan367f3432024-02-13 23:05:58 +00006317TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006318 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006319
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006320 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006321 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006322 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006323 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006324
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006325 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006326 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006327 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006328 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006329
6330 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006331 mDispatcher->onWindowInfosChanged(
6332 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006333
6334 PointF pointInFirst = {300, 200};
6335 PointF pointInSecond = {300, 600};
6336
6337 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006338 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006339 AINPUT_SOURCE_TOUCHSCREEN,
6340 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006341 // Only the first window should get the down event
6342 firstWindow->consumeMotionDown();
6343 secondWindow->assertNoEvents();
6344
6345 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006346 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006347 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006348 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006349 // The first window gets a move and the second a down
6350 firstWindow->consumeMotionMove();
6351 secondWindow->consumeMotionDown();
6352
Prabir Pradhan367f3432024-02-13 23:05:58 +00006353 // Transfer touch to the second window
6354 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006355 // The first window gets cancel and the new gets pointer down (it already saw down)
6356 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006357 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006358 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006359
6360 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006361 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006362 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006363 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006364 // The first window gets nothing and the second gets pointer up
6365 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006366 secondWindow->consumeMotionPointerUp(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006367 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006368
6369 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006370 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006371 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006372 // The first window gets nothing and the second gets up
6373 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006374 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6375 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006376}
6377
Prabir Pradhan367f3432024-02-13 23:05:58 +00006378// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
6379// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
6380// receiving touch is not supported, so the touch should continue on those windows and the
6381// transferred-to window should get nothing.
6382TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006383 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6384
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006385 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006386 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006387 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006388 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006389
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006390 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006391 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006392 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006393 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006394
6395 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006396 mDispatcher->onWindowInfosChanged(
6397 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006398
6399 PointF pointInFirst = {300, 200};
6400 PointF pointInSecond = {300, 600};
6401
6402 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006403 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006404 AINPUT_SOURCE_TOUCHSCREEN,
6405 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006406 // Only the first window should get the down event
6407 firstWindow->consumeMotionDown();
6408 secondWindow->assertNoEvents();
6409
6410 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006411 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006412 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006413 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006414 // The first window gets a move and the second a down
6415 firstWindow->consumeMotionMove();
6416 secondWindow->consumeMotionDown();
6417
6418 // Transfer touch focus to the second window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006419 const bool transferred = mDispatcher->transferTouchOnDisplay(secondWindow->getToken(),
6420 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006421 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006422 ASSERT_FALSE(transferred);
6423 firstWindow->assertNoEvents();
6424 secondWindow->assertNoEvents();
6425
6426 // The rest of the dispatch should proceed as normal
6427 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006428 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006429 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006430 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006431 // The first window gets MOVE and the second gets pointer up
6432 firstWindow->consumeMotionMove();
6433 secondWindow->consumeMotionUp();
6434
6435 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006436 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006437 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006438 // The first window gets nothing and the second gets up
6439 firstWindow->consumeMotionUp();
6440 secondWindow->assertNoEvents();
6441}
6442
Arthur Hungabbb9d82021-09-01 14:52:30 +00006443// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00006444// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00006445// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006446TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006447 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6448 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006449 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6450 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006451 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006452 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006453 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6454 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006455 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006456
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006457 sp<FakeWindowHandle> mirrorWindowInPrimary =
6458 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006459 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006460
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006461 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006462 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006463
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006464 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006465 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006466
6467 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006468 mDispatcher->onWindowInfosChanged(
6469 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6470 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6471 *secondWindowInPrimary->getInfo()},
6472 {},
6473 0,
6474 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006475
6476 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006477 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6478 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006479 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6480
6481 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006482 firstWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006483
Prabir Pradhan367f3432024-02-13 23:05:58 +00006484 // Transfer touch
6485 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
6486 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006487 // The first window gets cancel.
6488 firstWindowInPrimary->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006489 secondWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006490 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006491
6492 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006493 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006494 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006495 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6496 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006497 secondWindowInPrimary->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006498 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006499
6500 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006501 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006502 {150, 50}))
6503 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6504 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006505 secondWindowInPrimary->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6506 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006507}
6508
Prabir Pradhan367f3432024-02-13 23:05:58 +00006509// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
6510// 'transferTouchOnDisplay' api.
6511TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006512 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6513 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006514 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6515 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006516 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006517 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006518 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6519 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006520 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006521
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006522 sp<FakeWindowHandle> mirrorWindowInPrimary =
6523 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006524 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006525
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006526 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006527 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006528
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006529 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006530 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006531
6532 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006533 mDispatcher->onWindowInfosChanged(
6534 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6535 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6536 *secondWindowInPrimary->getInfo()},
6537 {},
6538 0,
6539 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006540
6541 // Touch on second display.
6542 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006543 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6544 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006545 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6546
6547 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006548 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006549
6550 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00006551 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
6552 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006553
6554 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006555 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006556 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
6557 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006558
6559 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006560 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006561 SECOND_DISPLAY_ID, {150, 50}))
6562 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006563 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006564 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
6565 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006566
6567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006568 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006569 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006570 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006571 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006572}
6573
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006574TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006575 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006576 sp<FakeWindowHandle> window =
6577 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6578 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006579
Vishnu Nair47074b82020-08-14 11:54:47 -07006580 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006581 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006582 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006583
6584 window->consumeFocusEvent(true);
6585
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006586 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006587
6588 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006589 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006590
6591 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006592 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006593 mFakePolicy->assertUserActivityPoked();
6594}
6595
6596TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
6597 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006598 sp<FakeWindowHandle> window =
6599 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6600 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006601
6602 window->setDisableUserActivity(true);
6603 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006604 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006605 setFocusedWindow(window);
6606
6607 window->consumeFocusEvent(true);
6608
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006609 mDispatcher->notifyKey(
6610 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006611
6612 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006613 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006614
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006615 // Should have not poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006616 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006617 mFakePolicy->assertUserActivityNotPoked();
6618}
6619
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006620TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyConsumedKey) {
Josep del Riob3981622023-04-18 15:49:45 +00006621 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006622 sp<FakeWindowHandle> window =
6623 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6624 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006625
6626 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006627 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006628 setFocusedWindow(window);
6629
6630 window->consumeFocusEvent(true);
6631
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006632 mFakePolicy->setConsumeKeyBeforeDispatching(true);
6633
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006634 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006635 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006636 mDispatcher->waitForIdle();
6637
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006638 // Key is not passed down
Josep del Riob3981622023-04-18 15:49:45 +00006639 window->assertNoEvents();
6640
6641 // Should have poked user activity
6642 mFakePolicy->assertUserActivityPoked();
6643}
6644
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006645TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserActivity) {
Josep del Riob3981622023-04-18 15:49:45 +00006646 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006647 sp<FakeWindowHandle> window =
6648 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6649 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006650
6651 window->setDisableUserActivity(true);
6652 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006653 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006654 setFocusedWindow(window);
6655
6656 window->consumeFocusEvent(true);
6657
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006658 mFakePolicy->setConsumeKeyBeforeDispatching(true);
6659
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006660 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006661 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006662 mDispatcher->waitForIdle();
6663
6664 // System key is not passed down
6665 window->assertNoEvents();
6666
6667 // Should have poked user activity
6668 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006669}
6670
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006671class DisableUserActivityInputDispatcherTest : public InputDispatcherTest,
6672 public ::testing::WithParamInterface<bool> {};
6673
6674TEST_P(DisableUserActivityInputDispatcherTest, NotPassedToUserUserActivity) {
6675 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6676 sp<FakeWindowHandle> window =
6677 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6678 ui::LogicalDisplayId::DEFAULT);
6679
6680 window->setDisableUserActivity(GetParam());
6681
6682 window->setFocusable(true);
6683 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6684 setFocusedWindow(window);
6685
6686 window->consumeFocusEvent(true);
6687
6688 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
6689 .keyCode(AKEYCODE_A)
6690 .policyFlags(0)
6691 .build());
6692 mDispatcher->waitForIdle();
6693
6694 // Key is not passed down
6695 window->assertNoEvents();
6696
6697 // Should not have poked user activity
6698 mFakePolicy->assertUserActivityNotPoked();
6699}
6700
6701INSTANTIATE_TEST_CASE_P(DisableUserActivity, DisableUserActivityInputDispatcherTest,
6702 ::testing::Bool());
6703
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006704TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
6705 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006706 sp<FakeWindowHandle> window =
6707 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6708 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006709
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006710 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006711
6712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006713 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006714 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006715 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6716
6717 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006718 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006719
6720 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006721 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006722 mFakePolicy->assertUserActivityPoked();
6723}
6724
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006725TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006726 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006727 sp<FakeWindowHandle> window =
6728 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6729 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006730
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006731 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006732
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006733 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006734 mDispatcher->waitForIdle();
6735
6736 window->assertNoEvents();
6737}
6738
6739// If a window is touchable, but does not have focus, it should receive motion events, but not keys
6740TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07006741 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006742 sp<FakeWindowHandle> window =
6743 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6744 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006745
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006746 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006747
6748 // Send key
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006749 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006750 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00006751 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006752 AINPUT_SOURCE_TOUCHSCREEN,
6753 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006754
6755 // Window should receive only the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006756 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006757 window->assertNoEvents(); // Key event or focus event will not be received
6758}
6759
arthurhungea3f4fc2020-12-21 23:18:53 +08006760TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
6761 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6762
arthurhungea3f4fc2020-12-21 23:18:53 +08006763 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006764 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006765 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006766 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08006767
arthurhungea3f4fc2020-12-21 23:18:53 +08006768 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006769 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006770 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006771 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08006772
6773 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006774 mDispatcher->onWindowInfosChanged(
6775 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08006776
6777 PointF pointInFirst = {300, 200};
6778 PointF pointInSecond = {300, 600};
6779
6780 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006781 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006782 AINPUT_SOURCE_TOUCHSCREEN,
6783 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006784 // Only the first window should get the down event
6785 firstWindow->consumeMotionDown();
6786 secondWindow->assertNoEvents();
6787
6788 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006789 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006790 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006791 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006792 // The first window gets a move and the second a down
6793 firstWindow->consumeMotionMove();
6794 secondWindow->consumeMotionDown();
6795
6796 // Send pointer cancel to the second window
6797 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006798 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
6799 ui::LogicalDisplayId::DEFAULT, {pointInFirst, pointInSecond});
arthurhungea3f4fc2020-12-21 23:18:53 +08006800 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006801 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006802 // The first window gets move and the second gets cancel.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006803 firstWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6804 secondWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
arthurhungea3f4fc2020-12-21 23:18:53 +08006805
6806 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006807 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006808 ui::LogicalDisplayId::DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006809 // The first window gets up and the second gets nothing.
6810 firstWindow->consumeMotionUp();
6811 secondWindow->assertNoEvents();
6812}
6813
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006814TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6815 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6816
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006817 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6818 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006819 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006820 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6821 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6822 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6823
Harry Cutts33476232023-01-30 19:57:29 +00006824 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006825 window->assertNoEvents();
6826 mDispatcher->waitForIdle();
6827}
6828
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006829using InputDispatcherMonitorTest = InputDispatcherTest;
6830
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006831/**
6832 * Two entities that receive touch: A window, and a global monitor.
6833 * The touch goes to the window, and then the window disappears.
6834 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
6835 * for the monitor, as well.
6836 * 1. foregroundWindow
6837 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
6838 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006839TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006840 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006841 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
6842 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006843
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006844 FakeMonitorReceiver monitor =
6845 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006846
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006847 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006848 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006849 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6850 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006851 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6852
6853 // Both the foreground window and the global monitor should receive the touch down
6854 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006855 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006856
6857 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006858 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006859 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006860 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6861
6862 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006863 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006864
6865 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006866 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006867 window->consumeMotionCancel();
6868 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
6869
6870 // If more events come in, there will be no more foreground window to send them to. This will
6871 // cause a cancel for the monitor, as well.
6872 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006873 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006874 ui::LogicalDisplayId::DEFAULT, {120, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006875 << "Injection should fail because the window was removed";
6876 window->assertNoEvents();
6877 // Global monitor now gets the cancel
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006878 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006879}
6880
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006881TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07006882 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006883 sp<FakeWindowHandle> window =
6884 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6885 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006886 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006887
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006888 FakeMonitorReceiver monitor =
6889 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006890
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006891 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006892 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6893 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006894 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006895 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
6896 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006897}
6898
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006899TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006900 FakeMonitorReceiver monitor =
6901 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006902
Chris Yea209fde2020-07-22 13:54:51 -07006903 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006904 sp<FakeWindowHandle> window =
6905 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6906 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006907 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00006908
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006909 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006910 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6911 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006912 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006913 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
6914 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006915
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006916 // Pilfer pointers from the monitor.
6917 // This should not do anything and the window should continue to receive events.
6918 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00006919
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006921 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006922 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08006923 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006924
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006925 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
6926 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00006927}
6928
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006929TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07006930 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006931 sp<FakeWindowHandle> window =
6932 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6933 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006934 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07006935 window->setWindowOffset(20, 40);
6936 window->setWindowTransform(0, 1, -1, 0);
6937
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006938 FakeMonitorReceiver monitor =
6939 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07006940
6941 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006942 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6943 ui::LogicalDisplayId::DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07006944 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006945 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08006946 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
6947 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07006948 // Even though window has transform, gesture monitor must not.
6949 ASSERT_EQ(ui::Transform(), event->getTransform());
6950}
6951
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006952TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00006953 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006954 FakeMonitorReceiver monitor =
6955 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00006956
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006957 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006958 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6959 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006960 << "Injection should fail if there is a monitor, but no touchable window";
6961 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00006962}
6963
Linnan Lid8150952024-01-26 18:07:17 +00006964/**
6965 * Two displays
6966 * The first monitor has a foreground window, a monitor
6967 * The second window has only one monitor.
6968 * We first inject a Down event into the first display, this injection should succeed and both
6969 * the foreground window and monitor should receive a down event, then inject a Down event into
6970 * the second display as well, this injection should fail, at this point, the first display
6971 * window and monitor should not receive a cancel or any other event.
6972 * Continue to inject Move and UP events to the first display, the events should be received
6973 * normally by the foreground window and monitor.
6974 */
6975TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
6976 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006977 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
6978 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006979
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006980 FakeMonitorReceiver monitor =
6981 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006982 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
6983
6984 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6985 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006986 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6987 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00006988 << "The down event injected into the first display should succeed";
6989
6990 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006991 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00006992
6993 ASSERT_EQ(InputEventInjectionResult::FAILED,
6994 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6995 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00006996 << "The down event injected into the second display should fail since there's no "
6997 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00006998
6999 // Continue to inject event to first display.
7000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7001 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007002 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007003 << "The move event injected into the first display should succeed";
7004
7005 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007006 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007007
7008 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007009 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007010 {110, 220}))
7011 << "The up event injected into the first display should succeed";
7012
7013 window->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007014 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007015
7016 window->assertNoEvents();
7017 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007018 secondMonitor.assertNoEvents();
7019}
7020
7021/**
7022 * Two displays
7023 * There is a monitor and foreground window on each display.
7024 * First, we inject down events into each of the two displays, at this point, the foreground windows
7025 * and monitors on both displays should receive down events.
7026 * At this point, the foreground window of the second display goes away, the gone window should
7027 * receive the cancel event, and the other windows and monitors should not receive any events.
7028 * Inject a move event into the second display. At this point, the injection should fail because
7029 * the second display no longer has a foreground window. At this point, the monitor on the second
7030 * display should receive a cancel event, and any windows or monitors on the first display should
7031 * not receive any events, and any subsequent injection of events into the second display should
7032 * also fail.
7033 * Continue to inject events into the first display, and the events should all be injected
7034 * successfully and received normally.
7035 */
7036TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
7037 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007038 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7039 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007040 sp<FakeWindowHandle> secondWindow =
7041 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
7042 SECOND_DISPLAY_ID);
7043
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007044 FakeMonitorReceiver monitor =
7045 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007046 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7047
7048 // There is a foreground window on both displays.
7049 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7050 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007051 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7052 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007053 << "The down event injected into the first display should succeed";
7054
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007055 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7056 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007057
7058 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7059 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7060 {100, 200}))
7061 << "The down event injected into the second display should succeed";
7062
Linnan Lid8150952024-01-26 18:07:17 +00007063 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
7064 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
7065
7066 // Now second window is gone away.
7067 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7068
7069 // The gone window should receive a cancel, and the monitor on the second display should not
7070 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00007071 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
7072 secondMonitor.assertNoEvents();
7073
7074 ASSERT_EQ(InputEventInjectionResult::FAILED,
7075 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7076 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007077 << "The move event injected into the second display should fail because there's no "
7078 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007079 // Now the monitor on the second display should receive a cancel event.
7080 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00007081
7082 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7083 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007084 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007085 << "The move event injected into the first display should succeed";
7086
7087 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007088 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007089
7090 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007091 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7092 {110, 220}))
7093 << "The up event injected into the second display should fail because there's no "
7094 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007095
7096 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007097 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007098 {110, 220}))
7099 << "The up event injected into the first display should succeed";
7100
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007101 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
7102 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007103
Linnan Lid8150952024-01-26 18:07:17 +00007104 window->assertNoEvents();
7105 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007106 secondWindow->assertNoEvents();
7107 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007108}
7109
7110/**
7111 * One display with transform
7112 * There is a foreground window and a monitor on the display
7113 * Inject down event and move event sequentially, the foreground window and monitor can receive down
7114 * event and move event, then let the foreground window go away, the foreground window receives
7115 * cancel event, inject move event again, the monitor receives cancel event, all the events received
7116 * by the monitor should be with the same transform as the display
7117 */
7118TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
7119 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007120 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7121 ui::LogicalDisplayId::DEFAULT);
7122 FakeMonitorReceiver monitor =
7123 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007124
7125 ui::Transform transform;
7126 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7127
7128 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007129 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Linnan Lid8150952024-01-26 18:07:17 +00007130 displayInfo.transform = transform;
7131
7132 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
7133
7134 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007135 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7136 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007137 << "The down event injected should succeed";
7138
7139 window->consumeMotionDown();
7140 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
7141 EXPECT_EQ(transform, downMotionEvent->getTransform());
7142 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
7143
7144 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7145 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007146 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007147 << "The move event injected should succeed";
7148
7149 window->consumeMotionMove();
7150 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
7151 EXPECT_EQ(transform, moveMotionEvent->getTransform());
7152 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
7153
7154 // Let foreground window gone
7155 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
7156
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007157 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00007158 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00007159
7160 ASSERT_EQ(InputEventInjectionResult::FAILED,
7161 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007162 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007163 << "The move event injected should failed";
7164 // Now foreground should not receive any events, but monitor should receive a cancel event
7165 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00007166 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
7167 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007168 EXPECT_EQ(ui::LogicalDisplayId::DEFAULT, cancelMotionEvent->getDisplayId());
Linnan Lid8150952024-01-26 18:07:17 +00007169 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
7170
7171 // Other event inject to this display should fail.
7172 ASSERT_EQ(InputEventInjectionResult::FAILED,
7173 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007174 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007175 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00007176 window->assertNoEvents();
7177 monitor.assertNoEvents();
7178}
7179
chaviw81e2bb92019-12-18 15:03:51 -08007180TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007181 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007182 sp<FakeWindowHandle> window =
7183 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7184 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007185
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007186 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08007187
7188 NotifyMotionArgs motionArgs =
7189 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007190 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007191
Prabir Pradhan678438e2023-04-13 19:32:51 +00007192 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08007193 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007194 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007195
7196 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08007197 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08007198 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7199 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
7200 motionArgs.pointerCoords[0].getX() - 10);
7201
Prabir Pradhan678438e2023-04-13 19:32:51 +00007202 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007203 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08007204}
7205
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007206/**
7207 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
7208 * the device default right away. In the test scenario, we check both the default value,
7209 * and the action of enabling / disabling.
7210 */
7211TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07007212 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007213 sp<FakeWindowHandle> window =
7214 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7215 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08007216 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007217
7218 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007219 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007220 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007221
7222 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007223 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007224 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007225 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007226
7227 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007228 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007229 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007230 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007231
7232 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007233 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007234 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007235 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07007236 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007237 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007238 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007239 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007240
7241 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007242 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007243 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007244 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007245
7246 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007247 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007248 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007249 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07007250 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007251 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007252 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007253 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007254
7255 window->assertNoEvents();
7256}
7257
Gang Wange9087892020-01-07 12:17:14 -05007258TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007259 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007260 sp<FakeWindowHandle> window =
7261 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7262 ui::LogicalDisplayId::DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05007263
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007264 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007265 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05007266
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007267 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007268 setFocusedWindow(window);
7269
Harry Cutts33476232023-01-30 19:57:29 +00007270 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05007271
Prabir Pradhan678438e2023-04-13 19:32:51 +00007272 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
7273 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05007274
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007275 std::unique_ptr<KeyEvent> event = window->consumeKey();
7276 ASSERT_NE(event, nullptr);
7277 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05007278 ASSERT_NE(verified, nullptr);
7279 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
7280
7281 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
7282 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
7283 ASSERT_EQ(keyArgs.source, verified->source);
7284 ASSERT_EQ(keyArgs.displayId, verified->displayId);
7285
7286 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
7287
7288 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05007289 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007290 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05007291 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
7292 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
7293 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
7294 ASSERT_EQ(0, verifiedKey.repeatCount);
7295}
7296
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007297TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007298 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007299 sp<FakeWindowHandle> window =
7300 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7301 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007302
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007303 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007304
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007305 ui::Transform transform;
7306 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7307
7308 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007309 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007310 displayInfo.transform = transform;
7311
Patrick Williamsd828f302023-04-28 17:52:08 -05007312 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007313
Prabir Pradhan678438e2023-04-13 19:32:51 +00007314 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007315 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007316 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007317 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007318
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007319 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
7320 ASSERT_NE(nullptr, event);
7321 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007322 ASSERT_NE(verified, nullptr);
7323 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
7324
7325 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
7326 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
7327 EXPECT_EQ(motionArgs.source, verified->source);
7328 EXPECT_EQ(motionArgs.displayId, verified->displayId);
7329
7330 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
7331
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007332 const vec2 rawXY =
7333 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
7334 motionArgs.pointerCoords[0].getXYValue());
7335 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
7336 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007337 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007338 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007339 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007340 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
7341 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
7342}
7343
chaviw09c8d2d2020-08-24 15:48:26 -07007344/**
7345 * Ensure that separate calls to sign the same data are generating the same key.
7346 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
7347 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
7348 * tests.
7349 */
7350TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
7351 KeyEvent event = getTestKeyEvent();
7352 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7353
7354 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
7355 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
7356 ASSERT_EQ(hmac1, hmac2);
7357}
7358
7359/**
7360 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
7361 */
7362TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
7363 KeyEvent event = getTestKeyEvent();
7364 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7365 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
7366
7367 verifiedEvent.deviceId += 1;
7368 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7369
7370 verifiedEvent.source += 1;
7371 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7372
7373 verifiedEvent.eventTimeNanos += 1;
7374 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7375
Linnan Li13bf76a2024-05-05 19:18:02 +08007376 verifiedEvent.displayId = ui::LogicalDisplayId{verifiedEvent.displayId.val() + 1};
chaviw09c8d2d2020-08-24 15:48:26 -07007377 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7378
7379 verifiedEvent.action += 1;
7380 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7381
7382 verifiedEvent.downTimeNanos += 1;
7383 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7384
7385 verifiedEvent.flags += 1;
7386 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7387
7388 verifiedEvent.keyCode += 1;
7389 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7390
7391 verifiedEvent.scanCode += 1;
7392 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7393
7394 verifiedEvent.metaState += 1;
7395 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7396
7397 verifiedEvent.repeatCount += 1;
7398 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7399}
7400
Vishnu Nair958da932020-08-21 17:12:37 -07007401TEST_F(InputDispatcherTest, SetFocusedWindow) {
7402 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007403 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7404 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007405 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007406 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7407 ui::LogicalDisplayId::DEFAULT);
7408 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007409
7410 // Top window is also focusable but is not granted focus.
7411 windowTop->setFocusable(true);
7412 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007413 mDispatcher->onWindowInfosChanged(
7414 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007415 setFocusedWindow(windowSecond);
7416
7417 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007418 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007419 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007420
7421 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007422 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007423 windowTop->assertNoEvents();
7424}
7425
7426TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
7427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007428 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7429 ui::LogicalDisplayId::DEFAULT);
7430 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007431
7432 window->setFocusable(true);
7433 // Release channel for window is no longer valid.
7434 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007435 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007436 setFocusedWindow(window);
7437
7438 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007439 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007440
7441 // window channel is invalid, so it should not receive any input event.
7442 window->assertNoEvents();
7443}
7444
7445TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
7446 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007447 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7448 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007449 window->setFocusable(false);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007450 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007451
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007452 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007453 setFocusedWindow(window);
7454
7455 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007456 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007457
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007458 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07007459 window->assertNoEvents();
7460}
7461
7462TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
7463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007464 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7465 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007466 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007467 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7468 ui::LogicalDisplayId::DEFAULT);
7469 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007470
7471 windowTop->setFocusable(true);
7472 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007473 mDispatcher->onWindowInfosChanged(
7474 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007475 setFocusedWindow(windowTop);
7476 windowTop->consumeFocusEvent(true);
7477
Chavi Weingarten847e8512023-03-29 00:26:09 +00007478 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007479 mDispatcher->onWindowInfosChanged(
7480 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007481 windowSecond->consumeFocusEvent(true);
7482 windowTop->consumeFocusEvent(false);
7483
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007484 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007485 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007486
7487 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007488 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007489}
7490
Chavi Weingarten847e8512023-03-29 00:26:09 +00007491TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07007492 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007493 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7494 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007495 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007496 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7497 ui::LogicalDisplayId::DEFAULT);
7498 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007499
7500 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00007501 windowSecond->setFocusable(false);
7502 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007503 mDispatcher->onWindowInfosChanged(
7504 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00007505 setFocusedWindow(windowTop);
7506 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07007507
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007508 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00007509 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007510
7511 // Event should be dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007512 windowTop->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007513 windowSecond->assertNoEvents();
7514}
7515
7516TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
7517 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007518 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7519 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007520 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007521 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007522 ui::LogicalDisplayId::DEFAULT);
7523 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007524
7525 window->setFocusable(true);
7526 previousFocusedWindow->setFocusable(true);
7527 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007528 mDispatcher->onWindowInfosChanged(
7529 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007530 setFocusedWindow(previousFocusedWindow);
7531 previousFocusedWindow->consumeFocusEvent(true);
7532
7533 // Requesting focus on invisible window takes focus from currently focused window.
7534 setFocusedWindow(window);
7535 previousFocusedWindow->consumeFocusEvent(false);
7536
7537 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007538 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007539 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007540 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007541
7542 // Window does not get focus event or key down.
7543 window->assertNoEvents();
7544
7545 // Window becomes visible.
7546 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007547 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007548
7549 // Window receives focus event.
7550 window->consumeFocusEvent(true);
7551 // Focused window receives key down.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007552 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007553}
7554
Vishnu Nair599f1412021-06-21 10:39:58 -07007555TEST_F(InputDispatcherTest, DisplayRemoved) {
7556 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007557 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "window",
7558 ui::LogicalDisplayId::DEFAULT);
7559 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair599f1412021-06-21 10:39:58 -07007560
7561 // window is granted focus.
7562 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007563 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07007564 setFocusedWindow(window);
7565 window->consumeFocusEvent(true);
7566
7567 // When a display is removed window loses focus.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007568 mDispatcher->displayRemoved(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07007569 window->consumeFocusEvent(false);
7570}
7571
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007572/**
7573 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
7574 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
7575 * of the 'slipperyEnterWindow'.
7576 *
7577 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
7578 * a way so that the touched location is no longer covered by the top window.
7579 *
7580 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
7581 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
7582 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
7583 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
7584 * with ACTION_DOWN).
7585 * Thus, the touch has been transferred from the top window into the bottom window, because the top
7586 * window moved itself away from the touched location and had Flag::SLIPPERY.
7587 *
7588 * Even though the top window moved away from the touched location, it is still obscuring the bottom
7589 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
7590 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
7591 *
7592 * In this test, we ensure that the event received by the bottom window has
7593 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
7594 */
7595TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007596 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007597 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007598
7599 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007600 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007601
7602 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007603 sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7604 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007605 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007606 // Make sure this one overlaps the bottom window
7607 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
7608 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
7609 // one. Windows with the same owner are not considered to be occluding each other.
7610 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
7611
7612 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007613 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7614 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007615 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
7616
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007617 mDispatcher->onWindowInfosChanged(
7618 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007619
7620 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00007621 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007622 AINPUT_SOURCE_TOUCHSCREEN,
7623 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007624 slipperyExitWindow->consumeMotionDown();
7625 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007626 mDispatcher->onWindowInfosChanged(
7627 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007628
Prabir Pradhan678438e2023-04-13 19:32:51 +00007629 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007630 AINPUT_SOURCE_TOUCHSCREEN,
7631 ui::LogicalDisplayId::DEFAULT, {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007632
7633 slipperyExitWindow->consumeMotionCancel();
7634
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007635 slipperyEnterWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007636 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
7637}
7638
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007639/**
7640 * Two windows, one on the left and another on the right. The left window is slippery. The right
7641 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
7642 * touch moves from the left window into the right window, the gesture should continue to go to the
7643 * left window. Touch shouldn't slip because the right window can't receive touches. This test
7644 * reproduces a crash.
7645 */
7646TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
7647 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7648
7649 sp<FakeWindowHandle> leftSlipperyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007650 sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
7651 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007652 leftSlipperyWindow->setSlippery(true);
7653 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
7654
7655 sp<FakeWindowHandle> rightDropTouchesWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007656 sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
7657 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007658 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
7659 rightDropTouchesWindow->setDropInput(true);
7660
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007661 mDispatcher->onWindowInfosChanged(
7662 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007663
7664 // Start touch in the left window
7665 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7666 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7667 .build());
7668 leftSlipperyWindow->consumeMotionDown();
7669
7670 // And move it into the right window
7671 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7672 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7673 .build());
7674
7675 // Since the right window isn't eligible to receive input, touch does not slip.
7676 // The left window continues to receive the gesture.
7677 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7678 rightDropTouchesWindow->assertNoEvents();
7679}
7680
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007681/**
7682 * A single window is on screen first. Touch is injected into that window. Next, a second window
7683 * appears. Since the first window is slippery, touch will move from the first window to the second.
7684 */
7685TEST_F(InputDispatcherTest, InjectedTouchSlips) {
7686 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7687 sp<FakeWindowHandle> originalWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007688 sp<FakeWindowHandle>::make(application, mDispatcher, "Original",
7689 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007690 originalWindow->setFrame(Rect(0, 0, 200, 200));
7691 originalWindow->setSlippery(true);
7692
7693 sp<FakeWindowHandle> appearingWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007694 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing",
7695 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007696 appearingWindow->setFrame(Rect(0, 0, 200, 200));
7697
7698 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
7699
7700 // Touch down on the original window
7701 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7702 injectMotionEvent(*mDispatcher,
7703 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7704 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
7705 .build()));
7706 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7707
7708 // Now, a new window appears. This could be, for example, a notification shade that appears
7709 // after user starts to drag down on the launcher window.
7710 mDispatcher->onWindowInfosChanged(
7711 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
7712 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7713 injectMotionEvent(*mDispatcher,
7714 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7715 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
7716 .build()));
7717 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7718 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7720 injectMotionEvent(*mDispatcher,
7721 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7722 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
7723 .build()));
7724 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7725
7726 originalWindow->assertNoEvents();
7727 appearingWindow->assertNoEvents();
7728}
7729
Linnan Li49b2b202024-04-12 12:46:40 +08007730/**
7731 * Three windows:
7732 * - left window, which has FLAG_SLIPPERY, so it supports slippery exit
7733 * - right window
7734 * - spy window
7735 * The three windows do not overlap.
7736 *
7737 * We have two devices reporting events:
7738 * - Device A reports ACTION_DOWN, which lands in the left window
7739 * - Device B reports ACTION_DOWN, which lands in the spy window.
7740 * - Now, device B reports ACTION_MOVE events which move to the right window.
7741 *
7742 * The right window should not receive any events because the spy window is not a foreground window,
7743 * and also it does not support slippery touches.
7744 */
7745TEST_F(InputDispatcherTest, MultiDeviceSpyWindowSlipTest) {
7746 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7747 sp<FakeWindowHandle> leftWindow =
7748 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007749 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007750 leftWindow->setFrame(Rect(0, 0, 100, 100));
7751 leftWindow->setSlippery(true);
7752
7753 sp<FakeWindowHandle> rightWindow =
7754 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007755 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007756 rightWindow->setFrame(Rect(100, 0, 200, 100));
7757
7758 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007759 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
7760 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007761 spyWindow->setFrame(Rect(200, 0, 300, 100));
7762 spyWindow->setSpy(true);
7763 spyWindow->setTrustedOverlay(true);
7764
7765 mDispatcher->onWindowInfosChanged(
7766 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *spyWindow->getInfo()}, {}, 0, 0});
7767
7768 const DeviceId deviceA = 9;
7769 const DeviceId deviceB = 3;
7770
7771 // Tap on left window with device A
7772 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7773 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7774 .deviceId(deviceA)
7775 .build());
7776 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
7777
7778 // Tap on spy window with device B
7779 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7780 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
7781 .deviceId(deviceB)
7782 .build());
7783 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
7784
7785 // Move to right window with device B. Touches should not slip to the right window, because spy
7786 // window is not a foreground window, and it does not have FLAG_SLIPPERY
7787 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7788 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7789 .deviceId(deviceB)
7790 .build());
7791 leftWindow->assertNoEvents();
7792 rightWindow->assertNoEvents();
7793 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
7794}
7795
7796/**
7797 * Three windows arranged horizontally and without any overlap.
7798 * The left and right windows have FLAG_SLIPPERY. The middle window does not have any special flags.
7799 *
7800 * We have two devices reporting events:
7801 * - Device A reports ACTION_DOWN which lands in the left window
7802 * - Device B reports ACTION_DOWN which lands in the right window
7803 * - Device B reports ACTION_MOVE that shifts to the middle window.
7804 * This should cause touches for Device B to slip from the right window to the middle window.
7805 * The right window should receive ACTION_CANCEL for device B and the
7806 * middle window should receive down event for Device B.
7807 * If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
7808 */
7809TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
Siarhei Vishniakoudd56df12024-05-20 14:56:38 -07007810 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
Linnan Li49b2b202024-04-12 12:46:40 +08007811 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7812 sp<FakeWindowHandle> leftWindow =
7813 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007814 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007815 leftWindow->setFrame(Rect(0, 0, 100, 100));
7816 leftWindow->setSlippery(true);
7817
7818 sp<FakeWindowHandle> middleWindow =
7819 sp<FakeWindowHandle>::make(application, mDispatcher, "middle window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007820 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007821 middleWindow->setFrame(Rect(100, 0, 200, 100));
7822
7823 sp<FakeWindowHandle> rightWindow =
7824 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007825 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007826 rightWindow->setFrame(Rect(200, 0, 300, 100));
7827 rightWindow->setSlippery(true);
7828
7829 mDispatcher->onWindowInfosChanged(
7830 {{*leftWindow->getInfo(), *middleWindow->getInfo(), *rightWindow->getInfo()},
7831 {},
7832 0,
7833 0});
7834
7835 const DeviceId deviceA = 9;
7836 const DeviceId deviceB = 3;
7837
7838 // Tap on left window with device A
7839 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7840 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7841 .deviceId(deviceA)
7842 .build());
7843 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
7844
7845 // Tap on right window with device B
7846 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7847 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
7848 .deviceId(deviceB)
7849 .build());
7850 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
7851
7852 // Move to middle window with device B. Touches should slip to middle window, because right
7853 // window is a foreground window that's associated with device B and has FLAG_SLIPPERY.
7854 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7855 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7856 .deviceId(deviceB)
7857 .build());
7858 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
7859 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
7860
7861 // Move to middle window with device A. Touches should slip to middle window, because left
7862 // window is a foreground window that's associated with device A and has FLAG_SLIPPERY.
7863 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7864 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7865 .deviceId(deviceA)
7866 .build());
7867 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceA)));
7868 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
7869
7870 // Ensure that middle window can receive the remaining move events.
7871 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7872 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
7873 .deviceId(deviceB)
7874 .build());
7875 leftWindow->assertNoEvents();
7876 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
7877 rightWindow->assertNoEvents();
7878}
7879
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007880TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007881 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007882 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7883
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007884 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
7885 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007886 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007887 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007888
7889 sp<FakeWindowHandle> rightSpy =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007890 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy",
7891 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007892 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007893 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007894 rightSpy->setSpy(true);
7895 rightSpy->setTrustedOverlay(true);
7896
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007897 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
7898 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007899 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007900 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007901
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007902 mDispatcher->onWindowInfosChanged(
7903 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007904
7905 // Touch in the left window
7906 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7907 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7908 .build());
7909 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
7910 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007911 ASSERT_NO_FATAL_FAILURE(
7912 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007913
7914 // Touch another finger over the right windows
7915 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7916 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7917 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7918 .build());
7919 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
7920 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
7921 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
7922 mDispatcher->waitForIdle();
7923 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007924 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
7925 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007926
7927 // Release finger over left window. The UP actions are not treated as device interaction.
7928 // The windows that did not receive the UP pointer will receive MOVE events, but since this
7929 // is part of the UP action, we do not treat this as device interaction.
7930 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
7931 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7932 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7933 .build());
7934 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
7935 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7936 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7937 mDispatcher->waitForIdle();
7938 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7939
7940 // Move remaining finger
7941 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7942 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7943 .build());
7944 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
7945 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
7946 mDispatcher->waitForIdle();
7947 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007948 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007949
7950 // Release all fingers
7951 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
7952 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
7953 .build());
7954 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
7955 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
7956 mDispatcher->waitForIdle();
7957 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7958}
7959
7960TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
7961 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7962
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007963 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
7964 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007965 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007966 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007967
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007968 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007969 setFocusedWindow(window);
7970 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
7971
7972 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007973 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007974 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007975 ASSERT_NO_FATAL_FAILURE(
7976 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007977
7978 // The UP actions are not treated as device interaction.
7979 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007980 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00007981 mDispatcher->waitForIdle();
7982 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
7983}
7984
Prabir Pradhan5893d362023-11-17 04:30:40 +00007985TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
7986 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7987
7988 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007989 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007990 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007991 sp<FakeWindowHandle> right =
7992 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
7993 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007994 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007995 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
7996 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00007997 spy->setFrame(Rect(0, 0, 200, 100));
7998 spy->setTrustedOverlay(true);
7999 spy->setSpy(true);
8000
8001 mDispatcher->onWindowInfosChanged(
8002 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
8003
8004 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008005 NotifyMotionArgs notifyArgs =
8006 generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8007 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008008 mDispatcher->notifyMotion(notifyArgs);
8009
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008010 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008011 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
8012 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008013 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008014 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8015 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008016 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008017 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8018
8019 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008020 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8021 ui::LogicalDisplayId::DEFAULT, {PointF{150, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008022 mDispatcher->notifyMotion(notifyArgs);
8023
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008024 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008025 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
8026 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008027 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008028 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8029 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008030 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008031 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8032
8033 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
8034}
8035
Linnan Liccf6ce32024-04-11 20:32:13 +08008036/**
8037 * When a device reports a DOWN event, which lands in a window that supports splits, and then the
8038 * device then reports a POINTER_DOWN, which lands in the location of a non-existing window, then
8039 * the previous window should receive this event and not be dropped.
8040 */
8041TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
8042 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008043 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8044 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008045 window->setFrame(Rect(0, 0, 100, 100));
8046 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8047
8048 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8049 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8050 .build());
8051
8052 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
8053
8054 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8055 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8056 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
8057 .build());
8058
8059 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_1_DOWN)));
8060}
8061
8062/**
8063 * When deviceA reports a DOWN event, which lands in a window that supports splits, and then deviceB
8064 * also reports a DOWN event, which lands in the location of a non-existing window, then the
8065 * previous window should receive deviceB's event and it should be dropped.
8066 */
8067TEST_F(InputDispatcherMultiDeviceTest, SecondDeviceDownEventDroppedWithoutWindowTarget) {
8068 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008069 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8070 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008071 window->setFrame(Rect(0, 0, 100, 100));
8072 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8073
8074 const DeviceId deviceA = 9;
8075 const DeviceId deviceB = 3;
8076
8077 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8078 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8079 .deviceId(deviceA)
8080 .build());
8081 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8082
8083 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8084 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
8085 .deviceId(deviceB)
8086 .build());
8087 window->assertNoEvents();
8088}
8089
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008090class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
8091protected:
8092 std::shared_ptr<FakeApplicationHandle> mApp;
8093 sp<FakeWindowHandle> mWindow;
8094
8095 virtual void SetUp() override {
8096 InputDispatcherTest::SetUp();
8097
8098 mApp = std::make_shared<FakeApplicationHandle>();
8099
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008100 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window",
8101 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008102 mWindow->setFrame(Rect(0, 0, 100, 100));
8103
8104 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8105 setFocusedWindow(mWindow);
8106 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
8107 }
8108
8109 void setFallback(int32_t keycode) {
8110 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
8111 return KeyEventBuilder(event).keyCode(keycode).build();
8112 });
8113 }
8114
8115 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008116 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
8117 ASSERT_NE(nullptr, event);
8118 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008119 }
8120};
8121
8122TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
8123 mDispatcher->notifyKey(
8124 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8125 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8126 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8127}
8128
8129TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
8130 mDispatcher->notifyKey(
8131 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8132 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8133 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8134}
8135
8136TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
8137 mDispatcher->notifyKey(
8138 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8139
8140 // Do not handle this key event.
8141 consumeKey(/*handled=*/false,
8142 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8143 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8144
8145 // Since the policy did not request any fallback to be generated, ensure there are no events.
8146 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8147}
8148
8149TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
8150 setFallback(AKEYCODE_B);
8151 mDispatcher->notifyKey(
8152 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8153
8154 // Do not handle this key event.
8155 consumeKey(/*handled=*/false,
8156 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8157
8158 // Since the key was not handled, ensure the fallback event was dispatched instead.
8159 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8160 consumeKey(/*handled=*/true,
8161 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8162 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8163
8164 // Release the original key, and ensure the fallback key is also released.
8165 mDispatcher->notifyKey(
8166 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8167 consumeKey(/*handled=*/false,
8168 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8169 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8170 consumeKey(/*handled=*/true,
8171 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8172 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8173
8174 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8175 mWindow->assertNoEvents();
8176}
8177
8178TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
8179 setFallback(AKEYCODE_B);
8180 mDispatcher->notifyKey(
8181 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8182
8183 // Do not handle this key event, but handle the fallback.
8184 consumeKey(/*handled=*/false,
8185 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8186 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8187 consumeKey(/*handled=*/true,
8188 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8189 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8190
8191 // Release the original key, and ensure the fallback key is also released.
8192 mDispatcher->notifyKey(
8193 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8194 // But this time, the app handles the original key.
8195 consumeKey(/*handled=*/true,
8196 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8197 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8198 // Ensure the fallback key is canceled.
8199 consumeKey(/*handled=*/true,
8200 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8201 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8202
8203 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8204 mWindow->assertNoEvents();
8205}
8206
8207TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
8208 setFallback(AKEYCODE_B);
8209 mDispatcher->notifyKey(
8210 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8211
8212 // Do not handle this key event.
8213 consumeKey(/*handled=*/false,
8214 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8215 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8216 // App does not handle the fallback either, so ensure another fallback is not generated.
8217 setFallback(AKEYCODE_C);
8218 consumeKey(/*handled=*/false,
8219 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8220 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8221
8222 // Release the original key, and ensure the fallback key is also released.
8223 setFallback(AKEYCODE_B);
8224 mDispatcher->notifyKey(
8225 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8226 consumeKey(/*handled=*/false,
8227 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8228 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8229 consumeKey(/*handled=*/false,
8230 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8231 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8232
8233 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8234 mWindow->assertNoEvents();
8235}
8236
8237TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
8238 setFallback(AKEYCODE_B);
8239 mDispatcher->notifyKey(
8240 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8241
8242 // Do not handle this key event, so fallback is generated.
8243 consumeKey(/*handled=*/false,
8244 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8245 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8246 consumeKey(/*handled=*/true,
8247 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8248 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8249
8250 // Release the original key, but assume the policy is misbehaving and it
8251 // generates an inconsistent fallback to the one from the DOWN event.
8252 setFallback(AKEYCODE_C);
8253 mDispatcher->notifyKey(
8254 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8255 consumeKey(/*handled=*/false,
8256 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8257 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8258 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
8259 consumeKey(/*handled=*/true,
8260 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8261 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8262
8263 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8264 mWindow->assertNoEvents();
8265}
8266
8267TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
8268 setFallback(AKEYCODE_B);
8269 mDispatcher->notifyKey(
8270 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8271
8272 // Do not handle this key event, so fallback is generated.
8273 consumeKey(/*handled=*/false,
8274 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8275 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8276 consumeKey(/*handled=*/true,
8277 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8278 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8279
8280 // The original key is canceled.
8281 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
8282 .keyCode(AKEYCODE_A)
8283 .addFlag(AKEY_EVENT_FLAG_CANCELED)
8284 .build());
8285 consumeKey(/*handled=*/false,
8286 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8287 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8288 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8289 // Ensure the fallback key is also canceled due to the original key being canceled.
8290 consumeKey(/*handled=*/true,
8291 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8292 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8293
8294 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8295 mWindow->assertNoEvents();
8296}
8297
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008298TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00008299 setFallback(AKEYCODE_B);
8300 mDispatcher->notifyKey(
8301 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8302
8303 // Do not handle this key event.
8304 consumeKey(/*handled=*/false,
8305 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8306 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8307 consumeKey(/*handled=*/true,
8308 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8309 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8310
8311 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8312 // When the unhandled key is reported to the policy next, remove the input channel.
8313 mDispatcher->removeInputChannel(mWindow->getToken());
8314 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8315 });
8316 // Release the original key, and let the app now handle the previously unhandled key.
8317 // This should result in the previously generated fallback key to be cancelled.
8318 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
8319 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
8320 // without holding the lock, because it need to synchronously fetch the fallback key. While in
8321 // the policy call, we will now remove the input channel. Once the policy call returns, the
8322 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
8323 // not cause any crashes.
8324 mDispatcher->notifyKey(
8325 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8326 consumeKey(/*handled=*/true,
8327 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8328 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8329}
8330
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008331TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
8332 setFallback(AKEYCODE_B);
8333 mDispatcher->notifyKey(
8334 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8335
8336 // Do not handle this key event.
8337 consumeKey(/*handled=*/false,
8338 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8339 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8340 consumeKey(/*handled=*/true,
8341 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8342 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8343
8344 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8345 // When the unhandled key is reported to the policy next, remove the window.
8346 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8347 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8348 });
8349 // Release the original key, which the app will not handle. When this unhandled key is reported
8350 // to the policy, the window will be removed.
8351 mDispatcher->notifyKey(
8352 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8353 consumeKey(/*handled=*/false,
8354 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8355 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8356
8357 // Since the window was removed, it loses focus, and the channel state will be reset.
8358 consumeKey(/*handled=*/true,
8359 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8360 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8361 mWindow->consumeFocusEvent(false);
8362 mWindow->assertNoEvents();
8363}
8364
8365TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
8366 setFallback(AKEYCODE_B);
8367 mDispatcher->notifyKey(
8368 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8369
8370 // Do not handle this key event.
8371 consumeKey(/*handled=*/false,
8372 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8373 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8374 const auto [seq, event] = mWindow->receiveEvent();
8375 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
8376 ASSERT_EQ(event->getType(), InputEventType::KEY);
8377 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
8378 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8379 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8380
8381 // Remove the window now, which should generate a cancellations and make the window lose focus.
8382 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8383 consumeKey(/*handled=*/true,
8384 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8385 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8386 consumeKey(/*handled=*/true,
8387 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8388 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8389 mWindow->consumeFocusEvent(false);
8390
8391 // Finish the event by reporting it as handled.
8392 mWindow->finishEvent(*seq);
8393 mWindow->assertNoEvents();
8394}
8395
Garfield Tan1c7bc862020-01-28 13:24:04 -08008396class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
8397protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08008398 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
8399 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008400
Chris Yea209fde2020-07-22 13:54:51 -07008401 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008402 sp<FakeWindowHandle> mWindow;
8403
8404 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00008405 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008406
Prabir Pradhandae52792023-12-15 07:36:40 +00008407 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008408 setUpWindow();
8409 }
8410
8411 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07008412 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008413 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window",
8414 ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008415
Vishnu Nair47074b82020-08-14 11:54:47 -07008416 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008417 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008418 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008419 mWindow->consumeFocusEvent(true);
8420 }
8421
Chris Ye2ad95392020-09-01 13:44:44 -07008422 void sendAndConsumeKeyDown(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008423 NotifyKeyArgs keyArgs =
8424 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008425 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008426 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008427 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008428
8429 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008430 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008431 }
8432
8433 void expectKeyRepeatOnce(int32_t repeatCount) {
8434 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008435 mWindow->consumeKeyEvent(
8436 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008437 }
8438
Chris Ye2ad95392020-09-01 13:44:44 -07008439 void sendAndConsumeKeyUp(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008440 NotifyKeyArgs keyArgs =
8441 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008442 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008443 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008444 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008445
8446 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008447 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008448 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008449 }
Hu Guofe3c8f12023-09-22 17:20:15 +08008450
8451 void injectKeyRepeat(int32_t repeatCount) {
8452 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008453 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount,
8454 ui::LogicalDisplayId::DEFAULT))
Hu Guofe3c8f12023-09-22 17:20:15 +08008455 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8456 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08008457};
8458
8459TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00008460 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008461 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8462 expectKeyRepeatOnce(repeatCount);
8463 }
8464}
8465
8466TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00008467 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008468 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8469 expectKeyRepeatOnce(repeatCount);
8470 }
Harry Cutts33476232023-01-30 19:57:29 +00008471 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008472 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08008473 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8474 expectKeyRepeatOnce(repeatCount);
8475 }
8476}
8477
8478TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008479 sendAndConsumeKeyDown(/*deviceId=*/1);
8480 expectKeyRepeatOnce(/*repeatCount=*/1);
8481 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008482 mWindow->assertNoEvents();
8483}
8484
8485TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008486 sendAndConsumeKeyDown(/*deviceId=*/1);
8487 expectKeyRepeatOnce(/*repeatCount=*/1);
8488 sendAndConsumeKeyDown(/*deviceId=*/2);
8489 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008490 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00008491 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008492 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00008493 expectKeyRepeatOnce(/*repeatCount=*/2);
8494 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07008495 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00008496 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008497 mWindow->assertNoEvents();
8498}
8499
8500TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008501 sendAndConsumeKeyDown(/*deviceId=*/1);
8502 expectKeyRepeatOnce(/*repeatCount=*/1);
8503 sendAndConsumeKeyDown(/*deviceId=*/2);
8504 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008505 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00008506 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008507 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08008508 mWindow->assertNoEvents();
8509}
8510
liushenxiang42232912021-05-21 20:24:09 +08008511TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
8512 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00008513 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008514 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008515 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
liushenxiang42232912021-05-21 20:24:09 +08008516 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
8517 mWindow->assertNoEvents();
8518}
8519
Garfield Tan1c7bc862020-01-28 13:24:04 -08008520TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008521 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008522 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008523 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008524 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8525 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008526 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008527 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008528 }
8529}
8530
8531TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008532 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008533 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008534
8535 std::unordered_set<int32_t> idSet;
8536 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008537 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8538 ASSERT_NE(nullptr, repeatEvent);
8539 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008540 EXPECT_EQ(idSet.end(), idSet.find(id));
8541 idSet.insert(id);
8542 }
8543}
8544
Hu Guofe3c8f12023-09-22 17:20:15 +08008545TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
8546 injectKeyRepeat(0);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008547 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Hu Guofe3c8f12023-09-22 17:20:15 +08008548 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
8549 expectKeyRepeatOnce(repeatCount);
8550 }
8551 injectKeyRepeat(1);
8552 // Expect repeatCount to be 3 instead of 1
8553 expectKeyRepeatOnce(3);
8554}
8555
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008556/* Test InputDispatcher for MultiDisplay */
8557class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
8558public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008559 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008560 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08008561
Chris Yea209fde2020-07-22 13:54:51 -07008562 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008563 windowInPrimary = sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1",
8564 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008565
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008566 // Set focus window for primary display, but focused display would be second one.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008567 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07008568 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008569 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
8570
Vishnu Nair958da932020-08-21 17:12:37 -07008571 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008572 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08008573
Chris Yea209fde2020-07-22 13:54:51 -07008574 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008575 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008576 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008577 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008578 // Set focus display to second one.
8579 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +00008580 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
8581
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008582 // Set focus window for second display.
8583 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07008584 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008585 mDispatcher->onWindowInfosChanged(
8586 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008587 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008588 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008589 }
8590
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008591 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008592 InputDispatcherTest::TearDown();
8593
Chris Yea209fde2020-07-22 13:54:51 -07008594 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008595 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07008596 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008597 windowInSecondary.clear();
8598 }
8599
8600protected:
Chris Yea209fde2020-07-22 13:54:51 -07008601 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008602 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07008603 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008604 sp<FakeWindowHandle> windowInSecondary;
8605};
8606
8607TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
8608 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008609 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008610 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8611 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008612 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008613 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08008614 windowInSecondary->assertNoEvents();
8615
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008616 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008618 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008619 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08008620 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08008621 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08008622}
8623
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008624TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08008625 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008626 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008627 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008628 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008629 windowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08008630 windowInSecondary->assertNoEvents();
8631
8632 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008633 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008634 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08008635 windowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008636 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hungb92218b2018-08-14 12:00:21 +08008637
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008638 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008639 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08008640
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008641 // Old focus should receive a cancel event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008642 windowInSecondary->consumeKeyUp(ui::LogicalDisplayId::INVALID, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08008643
8644 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008645 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08008646 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008647 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08008648 windowInSecondary->assertNoEvents();
8649}
8650
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008651// Test per-display input monitors for motion event.
8652TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08008653 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008654 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08008655 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008656 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008657
8658 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008659 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008660 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8661 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008662 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008663 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
8664 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008665 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008666 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008667
8668 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008669 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008670 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008671 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008672 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008673 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08008674 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08008675 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008676
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08008677 // Lift up the touch from the second display
8678 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008679 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08008680 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8681 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
8682 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
8683
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008684 // Test inject a non-pointer motion event.
8685 // If specific a display, it will dispatch to the focused window of particular display,
8686 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008687 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008688 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL,
8689 ui::LogicalDisplayId::INVALID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008690 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008691 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008692 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008693 windowInSecondary->consumeMotionDown(ui::LogicalDisplayId::INVALID);
8694 monitorInSecondary.consumeMotionDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008695}
8696
8697// Test per-display input monitors for key event.
8698TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008699 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08008700 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008701 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08008702 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008703 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008704
8705 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008706 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008707 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008708 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008709 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008710 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
8711 monitorInSecondary.consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008712}
8713
Vishnu Nair958da932020-08-21 17:12:37 -07008714TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
8715 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008716 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2",
8717 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008718 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008719 mDispatcher->onWindowInfosChanged(
8720 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
8721 *windowInSecondary->getInfo()},
8722 {},
8723 0,
8724 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008725 setFocusedWindow(secondWindowInPrimary);
8726 windowInPrimary->consumeFocusEvent(false);
8727 secondWindowInPrimary->consumeFocusEvent(true);
8728
8729 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008731 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008732 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008733 windowInPrimary->assertNoEvents();
8734 windowInSecondary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008735 secondWindowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008736}
8737
Arthur Hungdfd528e2021-12-08 13:23:04 +00008738TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
8739 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008740 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008741 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008742 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008743
8744 // Test touch down on primary display.
8745 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008746 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8747 ui::LogicalDisplayId::DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008748 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008749 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
8750 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008751
8752 // Test touch down on second display.
8753 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008754 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008755 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8756 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
8757 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
8758
8759 // Trigger cancel touch.
8760 mDispatcher->cancelCurrentTouch();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008761 windowInPrimary->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
8762 monitorInPrimary.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008763 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
8764 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
8765
8766 // Test inject a move motion event, no window/monitor should receive the event.
8767 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008768 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008769 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008770 << "Inject motion event should return InputEventInjectionResult::FAILED";
8771 windowInPrimary->assertNoEvents();
8772 monitorInPrimary.assertNoEvents();
8773
8774 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008775 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00008776 SECOND_DISPLAY_ID, {110, 200}))
8777 << "Inject motion event should return InputEventInjectionResult::FAILED";
8778 windowInSecondary->assertNoEvents();
8779 monitorInSecondary.assertNoEvents();
8780}
8781
Hu Guocb134f12023-12-23 13:42:44 +00008782/**
8783 * Send a key to the primary display and to the secondary display.
8784 * Then cause the key on the primary display to be canceled by sending in a stale key.
8785 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
8786 * does not get canceled.
8787 */
8788TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
8789 // Send a key down on primary display
8790 mDispatcher->notifyKey(
8791 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008792 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008793 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8794 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008795 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
8796 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00008797 windowInSecondary->assertNoEvents();
8798
8799 // Send a key down on second display
8800 mDispatcher->notifyKey(
8801 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8802 .displayId(SECOND_DISPLAY_ID)
8803 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8804 .build());
8805 windowInSecondary->consumeKeyEvent(
8806 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
8807 windowInPrimary->assertNoEvents();
8808
8809 // Send a valid key up event on primary display that will be dropped because it is stale
8810 NotifyKeyArgs staleKeyUp =
8811 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008812 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008813 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8814 .build();
8815 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
8816 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
8817 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
8818 mDispatcher->notifyKey(staleKeyUp);
8819
8820 // Only the key gesture corresponding to the dropped event should receive the cancel event.
8821 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
8822 // receive any events.
8823 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008824 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
Hu Guocb134f12023-12-23 13:42:44 +00008825 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8826 windowInSecondary->assertNoEvents();
8827}
8828
8829/**
8830 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
8831 */
8832TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
8833 // Send touch down on primary display.
8834 mDispatcher->notifyMotion(
8835 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8836 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008837 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008838 .build());
8839 windowInPrimary->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008840 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00008841 windowInSecondary->assertNoEvents();
8842
8843 // Send touch down on second display.
8844 mDispatcher->notifyMotion(
8845 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8846 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8847 .displayId(SECOND_DISPLAY_ID)
8848 .build());
8849 windowInPrimary->assertNoEvents();
8850 windowInSecondary->consumeMotionEvent(
8851 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
8852
8853 // inject a valid MotionEvent on primary display that will be stale when it arrives.
8854 NotifyMotionArgs staleMotionUp =
8855 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008856 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008857 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
8858 .build();
8859 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
8860 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
8861 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
8862 mDispatcher->notifyMotion(staleMotionUp);
8863
8864 // For stale motion events, we let the gesture to complete. This behaviour is different from key
8865 // events, where we would cancel the current keys instead.
8866 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
8867 windowInSecondary->assertNoEvents();
8868}
8869
Jackal Guof9696682018-10-05 12:23:23 +08008870class InputFilterTest : public InputDispatcherTest {
8871protected:
Linnan Li13bf76a2024-05-05 19:18:02 +08008872 void testNotifyMotion(ui::LogicalDisplayId displayId, bool expectToBeFiltered,
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008873 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08008874 NotifyMotionArgs motionArgs;
8875
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008876 motionArgs =
8877 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008878 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008879 motionArgs =
8880 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008881 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008882 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08008883 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07008884 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008885 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08008886 } else {
8887 mFakePolicy->assertFilterInputEventWasNotCalled();
8888 }
8889 }
8890
8891 void testNotifyKey(bool expectToBeFiltered) {
8892 NotifyKeyArgs keyArgs;
8893
8894 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008895 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08008896 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008897 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08008898 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08008899
8900 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08008901 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08008902 } else {
8903 mFakePolicy->assertFilterInputEventWasNotCalled();
8904 }
8905 }
8906};
8907
8908// Test InputFilter for MotionEvent
8909TEST_F(InputFilterTest, MotionEvent_InputFilter) {
8910 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008911 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00008912 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008913
8914 // Enable InputFilter
8915 mDispatcher->setInputFilterEnabled(true);
8916 // Test touch on both primary and second display, and check if both events are filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008917 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true);
Harry Cutts101ee9b2023-07-06 18:04:14 +00008918 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08008919
8920 // Disable InputFilter
8921 mDispatcher->setInputFilterEnabled(false);
8922 // Test touch on both primary and second display, and check if both events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008923 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00008924 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008925}
8926
8927// Test InputFilter for KeyEvent
8928TEST_F(InputFilterTest, KeyEvent_InputFilter) {
8929 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008930 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008931
8932 // Enable InputFilter
8933 mDispatcher->setInputFilterEnabled(true);
8934 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008935 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08008936
8937 // Disable InputFilter
8938 mDispatcher->setInputFilterEnabled(false);
8939 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00008940 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08008941}
8942
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008943// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
8944// logical display coordinate space.
8945TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
8946 ui::Transform firstDisplayTransform;
8947 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
8948 ui::Transform secondDisplayTransform;
8949 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
8950
8951 std::vector<gui::DisplayInfo> displayInfos(2);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008952 displayInfos[0].displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008953 displayInfos[0].transform = firstDisplayTransform;
8954 displayInfos[1].displayId = SECOND_DISPLAY_ID;
8955 displayInfos[1].transform = secondDisplayTransform;
8956
Patrick Williamsd828f302023-04-28 17:52:08 -05008957 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008958
8959 // Enable InputFilter
8960 mDispatcher->setInputFilterEnabled(true);
8961
8962 // Ensure the correct transforms are used for the displays.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008963 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true,
8964 firstDisplayTransform);
Harry Cutts101ee9b2023-07-06 18:04:14 +00008965 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07008966}
8967
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008968class InputFilterInjectionPolicyTest : public InputDispatcherTest {
8969protected:
8970 virtual void SetUp() override {
8971 InputDispatcherTest::SetUp();
8972
8973 /**
8974 * We don't need to enable input filter to test the injected event policy, but we enabled it
8975 * here to make the tests more realistic, since this policy only matters when inputfilter is
8976 * on.
8977 */
8978 mDispatcher->setInputFilterEnabled(true);
8979
8980 std::shared_ptr<InputApplicationHandle> application =
8981 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008982 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008983 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008984
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008985 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008986 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008987 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008988 setFocusedWindow(mWindow);
8989 mWindow->consumeFocusEvent(true);
8990 }
8991
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00008992 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
8993 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00008994 KeyEvent event;
8995
8996 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
8997 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008998 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
8999 AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009000 const int32_t additionalPolicyFlags =
9001 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
9002 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009003 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009004 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009005 policyFlags | additionalPolicyFlags));
9006
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009007 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009008 }
9009
9010 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9011 int32_t flags) {
9012 MotionEvent event;
9013 PointerProperties pointerProperties[1];
9014 PointerCoords pointerCoords[1];
9015 pointerProperties[0].clear();
9016 pointerProperties[0].id = 0;
9017 pointerCoords[0].clear();
9018 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
9019 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
9020
9021 ui::Transform identityTransform;
9022 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9023 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
9024 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
9025 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
9026 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07009027 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07009028 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00009029 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009030
9031 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
9032 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009033 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009034 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009035 policyFlags | additionalPolicyFlags));
9036
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009037 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009038 }
9039
9040private:
9041 sp<FakeWindowHandle> mWindow;
9042};
9043
9044TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009045 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
9046 // filter. Without it, the event will no different from a regularly injected event, and the
9047 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00009048 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
9049 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009050}
9051
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009052TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009053 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009054 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009055 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
9056}
9057
9058TEST_F(InputFilterInjectionPolicyTest,
9059 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
9060 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009061 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009062 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009063}
9064
9065TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00009066 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
9067 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009068}
9069
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009070class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
9071protected:
9072 virtual void SetUp() override {
9073 InputDispatcherTest::SetUp();
9074
9075 std::shared_ptr<FakeApplicationHandle> application =
9076 std::make_shared<FakeApplicationHandle>();
9077 application->setDispatchingTimeout(100ms);
9078 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009079 ui::LogicalDisplayId::DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00009080 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009081 mWindow->setDispatchingTimeout(100ms);
9082 mWindow->setFocusable(true);
9083
9084 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009085 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009086
9087 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
9088 setFocusedWindow(mWindow);
9089 mWindow->consumeFocusEvent(true);
9090 }
9091
Linnan Li13bf76a2024-05-05 19:18:02 +08009092 void notifyAndConsumeMotion(int32_t action, uint32_t source, ui::LogicalDisplayId displayId,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009093 nsecs_t eventTime) {
9094 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
9095 .displayId(displayId)
9096 .eventTime(eventTime)
9097 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9098 .build());
9099 mWindow->consumeMotionEvent(WithMotionAction(action));
9100 }
9101
9102private:
9103 sp<FakeWindowHandle> mWindow;
9104};
9105
9106TEST_F_WITH_FLAGS(
9107 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
9108 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9109 rate_limit_user_activity_poke_in_dispatcher))) {
9110 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
9111
9112 // First event of type TOUCH. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009113 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009114 milliseconds_to_nanoseconds(50));
9115 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009116 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
9117 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009118
9119 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009120 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009121 milliseconds_to_nanoseconds(130));
9122 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009123 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
9124 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009125
9126 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009127 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9128 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009129 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009130 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
9131 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009132
9133 // Within 50ns of previous TOUCH event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009134 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009135 milliseconds_to_nanoseconds(140));
9136 mFakePolicy->assertUserActivityNotPoked();
9137
9138 // Within 50ns of previous OTHER event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009139 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9140 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009141 mFakePolicy->assertUserActivityNotPoked();
9142
9143 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
9144 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009145 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009146 milliseconds_to_nanoseconds(160));
9147 mFakePolicy->assertUserActivityNotPoked();
9148
9149 // 65ns > 50ns has passed since previous OTHER event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009150 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9151 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009152 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009153 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
9154 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009155
9156 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009157 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009158 milliseconds_to_nanoseconds(300));
9159 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009160 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
9161 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009162
9163 // Assert that there's no more user activity poke event.
9164 mFakePolicy->assertUserActivityNotPoked();
9165}
9166
9167TEST_F_WITH_FLAGS(
9168 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
9169 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9170 rate_limit_user_activity_poke_in_dispatcher))) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009171 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009172 milliseconds_to_nanoseconds(200));
9173 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009174 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
9175 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009176
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009177 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009178 milliseconds_to_nanoseconds(280));
9179 mFakePolicy->assertUserActivityNotPoked();
9180
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009181 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009182 milliseconds_to_nanoseconds(340));
9183 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009184 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
9185 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009186}
9187
9188TEST_F_WITH_FLAGS(
9189 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
9190 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9191 rate_limit_user_activity_poke_in_dispatcher))) {
9192 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
9193
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009194 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9195 20);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009196 mFakePolicy->assertUserActivityPoked();
9197
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009198 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9199 30);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009200 mFakePolicy->assertUserActivityPoked();
9201}
9202
chaviwfd6d3512019-03-25 13:23:49 -07009203class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009204 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07009205 InputDispatcherTest::SetUp();
9206
Chris Yea209fde2020-07-22 13:54:51 -07009207 std::shared_ptr<FakeApplicationHandle> application =
9208 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009209 mUnfocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
9210 ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009211 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07009212
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009213 mFocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
9214 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009215 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07009216
9217 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009218 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07009219 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07009220
9221 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009222 mDispatcher->onWindowInfosChanged(
9223 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009224 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009225 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07009226 }
9227
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009228 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07009229 InputDispatcherTest::TearDown();
9230
9231 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009232 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07009233 }
9234
9235protected:
9236 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009237 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07009238 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07009239};
9240
9241// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9242// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
9243// the onPointerDownOutsideFocus callback.
9244TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009245 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009246 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9247 ui::LogicalDisplayId::DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009248 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009249 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009250
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009251 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07009252 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
9253}
9254
9255// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
9256// DOWN on the window that doesn't have focus. Ensure no window received the
9257// onPointerDownOutsideFocus callback.
9258TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009259 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009260 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009261 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009262 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009263 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009264
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009265 ASSERT_TRUE(mDispatcher->waitForIdle());
9266 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009267}
9268
9269// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
9270// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
9271TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08009272 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009273 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009274 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009275 mFocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009276
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009277 ASSERT_TRUE(mDispatcher->waitForIdle());
9278 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009279}
9280
9281// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9282// DOWN on the window that already has focus. Ensure no window received the
9283// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009284TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009285 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009286 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9287 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009288 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009289 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009290
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009291 ASSERT_TRUE(mDispatcher->waitForIdle());
9292 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009293}
9294
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009295// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
9296// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
9297TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
9298 const MotionEvent event =
9299 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
9300 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009301 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009302 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
9303 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009304 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009305 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009306 mUnfocusedWindow->consumeAnyMotionDown(ui::LogicalDisplayId::DEFAULT,
9307 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009308
9309 ASSERT_TRUE(mDispatcher->waitForIdle());
9310 mFakePolicy->assertOnPointerDownWasNotCalled();
9311 // Ensure that the unfocused window did not receive any FOCUS events.
9312 mUnfocusedWindow->assertNoEvents();
9313}
9314
chaviwaf87b3e2019-10-01 16:59:28 -07009315// These tests ensures we can send touch events to a single client when there are multiple input
9316// windows that point to the same client token.
9317class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
9318 virtual void SetUp() override {
9319 InputDispatcherTest::SetUp();
9320
Chris Yea209fde2020-07-22 13:54:51 -07009321 std::shared_ptr<FakeApplicationHandle> application =
9322 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009323 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009324 ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009325 mWindow1->setFrame(Rect(0, 0, 100, 100));
9326
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009327 mWindow2 = mWindow1->clone(ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009328 mWindow2->setFrame(Rect(100, 100, 200, 200));
9329
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009330 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009331 }
9332
9333protected:
9334 sp<FakeWindowHandle> mWindow1;
9335 sp<FakeWindowHandle> mWindow2;
9336
9337 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05009338 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07009339 vec2 vals = windowInfo->transform.transform(point.x, point.y);
9340 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07009341 }
9342
9343 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
9344 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009345 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009346 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009347 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009348 ASSERT_NE(nullptr, motionEvent);
9349 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07009350
9351 for (size_t i = 0; i < points.size(); i++) {
9352 float expectedX = points[i].x;
9353 float expectedY = points[i].y;
9354
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009355 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009356 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009357 << ", got " << motionEvent->getX(i);
9358 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009359 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009360 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07009361 }
9362 }
chaviw9eaa22c2020-07-01 16:21:27 -07009363
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009364 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
9365 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07009366 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009367 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009368 ui::LogicalDisplayId::DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07009369
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009370 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009371 }
chaviwaf87b3e2019-10-01 16:59:28 -07009372};
9373
9374TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
9375 // Touch Window 1
9376 PointF touchedPoint = {10, 10};
9377 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009378 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009379
9380 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009381 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009382
9383 // Touch Window 2
9384 touchedPoint = {150, 150};
9385 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009386 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009387}
9388
chaviw9eaa22c2020-07-01 16:21:27 -07009389TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
9390 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07009391 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009392 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009393
9394 // Touch Window 1
9395 PointF touchedPoint = {10, 10};
9396 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009397 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009398 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009399 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009400
9401 // Touch Window 2
9402 touchedPoint = {150, 150};
9403 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009404 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
9405 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009406
chaviw9eaa22c2020-07-01 16:21:27 -07009407 // Update the transform so rotation is set
9408 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009409 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009410 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009411 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009412}
9413
chaviw9eaa22c2020-07-01 16:21:27 -07009414TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009415 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009416 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009417
9418 // Touch Window 1
9419 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9420 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009421 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009422
9423 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009424 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
9425 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
9426 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07009427 touchedPoints.push_back(PointF{150, 150});
9428 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009429 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009430
chaviw9eaa22c2020-07-01 16:21:27 -07009431 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009432 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009433 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009434
chaviw9eaa22c2020-07-01 16:21:27 -07009435 // Update the transform so rotation is set for Window 2
9436 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009437 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009438 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009439 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009440}
9441
chaviw9eaa22c2020-07-01 16:21:27 -07009442TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009443 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009444 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009445
9446 // Touch Window 1
9447 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9448 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009449 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009450
9451 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009452 touchedPoints.push_back(PointF{150, 150});
9453 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009454
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009455 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009456
9457 // Move both windows
9458 touchedPoints = {{20, 20}, {175, 175}};
9459 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9460 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9461
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009462 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009463
chaviw9eaa22c2020-07-01 16:21:27 -07009464 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009465 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009466 expectedPoints.pop_back();
9467
9468 // Touch Window 2
9469 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009470 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009471 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009472 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009473
9474 // Move both windows
9475 touchedPoints = {{20, 20}, {175, 175}};
9476 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9477 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9478
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009479 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009480}
9481
9482TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
9483 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009484 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009485
9486 // Touch Window 1
9487 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9488 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009489 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009490
9491 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009492 touchedPoints.push_back(PointF{150, 150});
9493 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009494
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009495 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009496
9497 // Move both windows
9498 touchedPoints = {{20, 20}, {175, 175}};
9499 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9500 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9501
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009502 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009503}
9504
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009505/**
9506 * When one of the windows is slippery, the touch should not slip into the other window with the
9507 * same input channel.
9508 */
9509TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
9510 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009511 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009512
9513 // Touch down in window 1
9514 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009515 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009516 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
9517
9518 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
9519 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
9520 // getting generated.
9521 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009522 ui::LogicalDisplayId::DEFAULT, {{150, 150}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009523
9524 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
9525}
9526
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009527/**
9528 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
9529 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
9530 * that the pointer is hovering over may have a different transform.
9531 */
9532TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009533 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009534
9535 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009536 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
9537 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9538 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009539 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
9540 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009541 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009542 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9543 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9544 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009545 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009546 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009547 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
9548}
9549
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009550class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
9551 virtual void SetUp() override {
9552 InputDispatcherTest::SetUp();
9553
Chris Yea209fde2020-07-22 13:54:51 -07009554 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009555 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009556 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009557 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009558 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009559 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07009560 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009561
9562 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009563 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009564
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009565 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009566 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009567 mWindow->consumeFocusEvent(true);
9568 }
9569
9570 virtual void TearDown() override {
9571 InputDispatcherTest::TearDown();
9572 mWindow.clear();
9573 }
9574
9575protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009576 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07009577 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009578 sp<FakeWindowHandle> mWindow;
9579 static constexpr PointF WINDOW_LOCATION = {20, 20};
9580
9581 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009582 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
9583 .x(WINDOW_LOCATION.x)
9584 .y(WINDOW_LOCATION.y);
9585 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9586 .pointer(touchingPointer)
9587 .build());
9588 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9589 .pointer(touchingPointer)
9590 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009591 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009592
9593 sp<FakeWindowHandle> addSpyWindow() {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009594 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy",
9595 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009596 spy->setTrustedOverlay(true);
9597 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009598 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009599 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009600 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009601 return spy;
9602 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009603};
9604
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009605// Send a tap and respond, which should not cause an ANR.
9606TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
9607 tapOnWindow();
9608 mWindow->consumeMotionDown();
9609 mWindow->consumeMotionUp();
9610 ASSERT_TRUE(mDispatcher->waitForIdle());
9611 mFakePolicy->assertNotifyAnrWasNotCalled();
9612}
9613
9614// Send a regular key and respond, which should not cause an ANR.
9615TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009616 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009617 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009618 ASSERT_TRUE(mDispatcher->waitForIdle());
9619 mFakePolicy->assertNotifyAnrWasNotCalled();
9620}
9621
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009622TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
9623 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009624 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009625 mWindow->consumeFocusEvent(false);
9626
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009627 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009628 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9629 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
9630 CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00009631 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009633 // Key will not go to window because we have no focused window.
9634 // The 'no focused window' ANR timer should start instead.
9635
9636 // Now, the focused application goes away.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009637 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, nullptr);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009638 // The key should get dropped and there should be no ANR.
9639
9640 ASSERT_TRUE(mDispatcher->waitForIdle());
9641 mFakePolicy->assertNotifyAnrWasNotCalled();
9642}
9643
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009644// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009645// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9646// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009647TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009648 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009649 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9650 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009651
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009652 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009653 ASSERT_TRUE(sequenceNum);
9654 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009655 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009656
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009657 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009658 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009659 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009660 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009661 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009662}
9663
9664// Send a key to the app and have the app not respond right away.
9665TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
9666 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009667 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009668 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009669 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009670 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009671 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009672 ASSERT_TRUE(mDispatcher->waitForIdle());
9673}
9674
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009675// We have a focused application, but no focused window
9676TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07009677 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009678 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009679 mWindow->consumeFocusEvent(false);
9680
9681 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009682 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009683 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9684 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009685 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9686 mDispatcher->waitForIdle();
9687 mFakePolicy->assertNotifyAnrWasNotCalled();
9688
9689 // Once a focused event arrives, we get an ANR for this application
9690 // We specify the injection timeout to be smaller than the application timeout, to ensure that
9691 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009692 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009693 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9694 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT, 50ms,
Linnan Li13bf76a2024-05-05 19:18:02 +08009695 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009696 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009697 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07009698 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009699 ASSERT_TRUE(mDispatcher->waitForIdle());
9700}
9701
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009702/**
9703 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
9704 * there will not be an ANR.
9705 */
9706TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
9707 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009708 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009709 mWindow->consumeFocusEvent(false);
9710
9711 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07009712 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
9713 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009714 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
9715 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
9716
9717 // Define a valid key down event that is stale (too old).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009718 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
9719 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN,
9720 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime,
9721 eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009722
Hu Guofe3c8f12023-09-22 17:20:15 +08009723 const int32_t policyFlags =
9724 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009725
9726 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00009727 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009728 InputEventInjectionSync::WAIT_FOR_RESULT,
9729 INJECT_EVENT_TIMEOUT, policyFlags);
9730 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
9731 << "Injection should fail because the event is stale";
9732
9733 ASSERT_TRUE(mDispatcher->waitForIdle());
9734 mFakePolicy->assertNotifyAnrWasNotCalled();
9735 mWindow->assertNoEvents();
9736}
9737
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009738// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009739// Make sure that we don't notify policy twice about the same ANR.
9740TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009741 const std::chrono::duration appTimeout = 400ms;
9742 mApplication->setDispatchingTimeout(appTimeout);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009743 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009744
Vishnu Nair47074b82020-08-14 11:54:47 -07009745 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009746 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009747 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009748
9749 // Once a focused event arrives, we get an ANR for this application
9750 // We specify the injection timeout to be smaller than the application timeout, to ensure that
9751 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009752 const std::chrono::duration eventInjectionTimeout = 100ms;
9753 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009754 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009755 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9756 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT,
9757 eventInjectionTimeout,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009758 /*allowKeyRepeat=*/false);
9759 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
9760 << "result=" << ftl::enum_string(result);
9761 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
9762 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
9763 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
9764 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009765
Vishnu Naire4df8752022-09-08 09:17:55 -07009766 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009767 // ANR should not be raised again. It is up to policy to do that if it desires.
9768 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009769
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009770 // If we now get a focused window, the ANR should stop, but the policy handles that via
9771 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009772 ASSERT_TRUE(mDispatcher->waitForIdle());
9773}
9774
9775// We have a focused application, but no focused window
9776TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07009777 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009778 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009779 mWindow->consumeFocusEvent(false);
9780
9781 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009782 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009783
Vishnu Naire4df8752022-09-08 09:17:55 -07009784 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9785 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009786
9787 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009788 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009789 ASSERT_TRUE(mDispatcher->waitForIdle());
9790 mWindow->assertNoEvents();
9791}
9792
9793/**
9794 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
9795 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
9796 * If we process 1 of the events, but ANR on the second event with the same timestamp,
9797 * the ANR mechanism should still work.
9798 *
9799 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
9800 * DOWN event, while not responding on the second one.
9801 */
9802TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
9803 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009804 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009805 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009806 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9807 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009808 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009809
9810 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009811 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009812 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009813 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9814 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009815 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009816
9817 // 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 -07009818 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009819 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009820 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009821}
9822
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009823// A spy window can receive an ANR
9824TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
9825 sp<FakeWindowHandle> spy = addSpyWindow();
9826
9827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009828 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9829 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009830 mWindow->consumeMotionDown();
9831
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009832 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009833 ASSERT_TRUE(sequenceNum);
9834 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009835 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009836
9837 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009838 spy->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009839 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009840 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009841 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009842}
9843
9844// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009845// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009846TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
9847 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009848
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009850 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
9851 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
9852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
9853 injectKeyUp(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009854
9855 // Stuck on the ACTION_UP
9856 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009857 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009858
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009859 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009860 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009861 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9862 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009863
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009864 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009865 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009866 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009867 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009868 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009869}
9870
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009871// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009872// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009873TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
9874 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009875
9876 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009877 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9878 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009879
9880 mWindow->consumeMotionDown();
9881 // Stuck on the ACTION_UP
9882 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009883 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009884
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009885 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009886 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009887 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
9888 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009889
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009890 mWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009891 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009892 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009893 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009894 spy->assertNoEvents();
9895}
9896
9897TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009898 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009899
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009900 FakeMonitorReceiver monitor =
9901 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009902
9903 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009904 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9905 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009906
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009907 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009908 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
9909 ASSERT_TRUE(consumeSeq);
9910
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009911 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
9912 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009913
9914 monitor.finishEvent(*consumeSeq);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009915 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009916
9917 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009918 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009919}
9920
9921// If a window is unresponsive, then you get anr. if the window later catches up and starts to
9922// process events, you don't get an anr. When the window later becomes unresponsive again, you
9923// get an ANR again.
9924// 1. tap -> block on ACTION_UP -> receive ANR
9925// 2. consume all pending events (= queue becomes healthy again)
9926// 3. tap again -> block on ACTION_UP again -> receive ANR second time
9927TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
9928 tapOnWindow();
9929
9930 mWindow->consumeMotionDown();
9931 // Block on ACTION_UP
9932 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009933 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009934 mWindow->consumeMotionUp(); // Now the connection should be healthy again
9935 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009936 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009937 mWindow->assertNoEvents();
9938
9939 tapOnWindow();
9940 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009941 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009942 mWindow->consumeMotionUp();
9943
9944 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009945 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009946 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009947 mWindow->assertNoEvents();
9948}
9949
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009950// If a connection remains unresponsive for a while, make sure policy is only notified once about
9951// it.
9952TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009954 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9955 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009956
9957 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009958 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009959 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009960 // 'notifyConnectionUnresponsive' should only be called once per connection
9961 mFakePolicy->assertNotifyAnrWasNotCalled();
9962 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009963 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009964 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009965 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009966 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009967 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -08009968 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009969 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009970}
9971
9972/**
9973 * 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 -07009974 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009975 */
9976TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009977 // The timeouts in this test are established by relying on the fact that the "key waiting for
9978 // events timeout" is equal to 500ms.
9979 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009980 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009981 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009982
9983 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009984 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009985 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009986 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009987 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009988
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009989 // Don't finish the events yet, and send a key
9990 mDispatcher->notifyKey(
9991 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
9992 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
9993 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009994 // Key will not be sent to the window, yet, because the window is still processing events
9995 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009996 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009997 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009998
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -08009999 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010000 // if we wait long enough though, dispatcher will give up, and still send the key
10001 // to the focused window, even though we have not yet finished the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010002 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010003 mWindow->finishEvent(*downSequenceNum);
10004 mWindow->finishEvent(*upSequenceNum);
10005}
10006
10007/**
10008 * If a window is processing a motion event, and then a key event comes in, the key event should
10009 * not go to the focused window until the motion is processed.
10010 * If then a new motion comes in, then the pending key event should be going to the currently
10011 * focused window right away.
10012 */
10013TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010014 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
10015 // The timeouts in this test are established by relying on the fact that the "key waiting for
10016 // events timeout" is equal to 500ms.
10017 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010018 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010019 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010020
10021 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010022 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010023 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010024 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010025 ASSERT_TRUE(upSequenceNum);
10026 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010027 mDispatcher->notifyKey(
10028 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10029 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10030 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010031 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010032 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010033
10034 // Now tap down again. It should cause the pending key to go to the focused window right away.
10035 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010036 // Now that we tapped, we should receive the key immediately.
10037 // Since there's still room for slowness, we use 200ms, which is much less than
10038 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
10039 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
10040 ASSERT_NE(nullptr, keyEvent);
10041 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
10042 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
10043 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
10044 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010045 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
10046 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010047 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10048 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010049 mWindow->assertNoEvents();
10050}
10051
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010052/**
10053 * Send an event to the app and have the app not respond right away.
10054 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10055 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
10056 * At some point, the window becomes responsive again.
10057 * Ensure that subsequent events get dropped, and the next gesture is delivered.
10058 */
10059TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
10060 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10061 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
10062 .build());
10063
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010064 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010065 ASSERT_TRUE(sequenceNum);
10066 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10067 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10068
10069 mWindow->finishEvent(*sequenceNum);
10070 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
10071 ASSERT_TRUE(mDispatcher->waitForIdle());
10072 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10073
10074 // Now that the window is responsive, let's continue the gesture.
10075 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10076 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10077 .build());
10078
10079 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10080 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10081 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10082 .build());
10083
10084 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10085 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10086 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10087 .build());
10088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10089 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10090 .build());
10091 // We already canceled this pointer, so the window shouldn't get any new events.
10092 mWindow->assertNoEvents();
10093
10094 // Start another one.
10095 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10096 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
10097 .build());
10098 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10099}
10100
Prabir Pradhanfc364722024-02-08 17:51:20 +000010101// Send an event to the app and have the app not respond right away. Then remove the app window.
10102// When the window is removed, the dispatcher will cancel the events for that window.
10103// So InputDispatcher will enqueue ACTION_CANCEL event as well.
10104TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
10105 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010106 AINPUT_SOURCE_TOUCHSCREEN,
10107 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010108
10109 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10110 ASSERT_TRUE(sequenceNum);
10111
10112 // Remove the window, but the input channel should remain alive.
10113 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10114
10115 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10116 // Since the window was removed, Dispatcher does not know the PID associated with the window
10117 // anymore, so the policy is notified without the PID.
10118 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
10119 /*pid=*/std::nullopt);
10120
10121 mWindow->finishEvent(*sequenceNum);
10122 // The cancellation was generated when the window was removed, along with the focus event.
10123 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010124 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010125 mWindow->consumeFocusEvent(false);
10126 ASSERT_TRUE(mDispatcher->waitForIdle());
10127 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10128}
10129
10130// Send an event to the app and have the app not respond right away. Wait for the policy to be
10131// notified of the unresponsive window, then remove the app window.
10132TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
10133 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010134 AINPUT_SOURCE_TOUCHSCREEN,
10135 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010136
10137 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10138 ASSERT_TRUE(sequenceNum);
10139 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10140 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10141
10142 // Remove the window, but the input channel should remain alive.
10143 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10144
10145 mWindow->finishEvent(*sequenceNum);
10146 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
10147 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010148 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010149 mWindow->consumeFocusEvent(false);
10150 ASSERT_TRUE(mDispatcher->waitForIdle());
10151 // Since the window was removed, Dispatcher does not know the PID associated with the window
10152 // becoming responsive, so the policy is notified without the PID.
10153 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10154}
10155
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010156class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
10157 virtual void SetUp() override {
10158 InputDispatcherTest::SetUp();
10159
Chris Yea209fde2020-07-22 13:54:51 -070010160 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010161 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010162 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010163 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010164 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010165 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010166 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010167
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010168 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010169 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010170 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010171 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010172
10173 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010174 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -070010175 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010176
10177 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010178 mDispatcher->onWindowInfosChanged(
10179 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010180 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010181 mFocusedWindow->consumeFocusEvent(true);
10182 }
10183
10184 virtual void TearDown() override {
10185 InputDispatcherTest::TearDown();
10186
10187 mUnfocusedWindow.clear();
10188 mFocusedWindow.clear();
10189 }
10190
10191protected:
Chris Yea209fde2020-07-22 13:54:51 -070010192 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010193 sp<FakeWindowHandle> mUnfocusedWindow;
10194 sp<FakeWindowHandle> mFocusedWindow;
10195 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
10196 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
10197 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
10198
10199 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
10200
10201 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
10202
10203private:
10204 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010205 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010206 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10207 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010208 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010209 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10210 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010211 }
10212};
10213
10214// If we have 2 windows that are both unresponsive, the one with the shortest timeout
10215// should be ANR'd first.
10216TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010217 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010218 injectMotionEvent(*mDispatcher,
10219 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10220 AINPUT_SOURCE_TOUCHSCREEN)
10221 .pointer(PointerBuilder(0, ToolType::FINGER)
10222 .x(FOCUSED_WINDOW_LOCATION.x)
10223 .y(FOCUSED_WINDOW_LOCATION.y))
10224 .build()));
10225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10226 injectMotionEvent(*mDispatcher,
10227 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
10228 AINPUT_SOURCE_TOUCHSCREEN)
10229 .pointer(PointerBuilder(0, ToolType::FINGER)
10230 .x(FOCUSED_WINDOW_LOCATION.x)
10231 .y(FOCUSED_WINDOW_LOCATION.y))
10232 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010233 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010234 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010235 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010236 // We consumed all events, so no ANR
10237 ASSERT_TRUE(mDispatcher->waitForIdle());
10238 mFakePolicy->assertNotifyAnrWasNotCalled();
10239
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010240 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010241 injectMotionEvent(*mDispatcher,
10242 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10243 AINPUT_SOURCE_TOUCHSCREEN)
10244 .pointer(PointerBuilder(0, ToolType::FINGER)
10245 .x(FOCUSED_WINDOW_LOCATION.x)
10246 .y(FOCUSED_WINDOW_LOCATION.y))
10247 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010248 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010249 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010250
10251 const std::chrono::duration timeout =
10252 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010253 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010254
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010255 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010256 mFocusedWindow->consumeMotionDown();
10257 // This cancel is generated because the connection was unresponsive
10258 mFocusedWindow->consumeMotionCancel();
10259 mFocusedWindow->assertNoEvents();
10260 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010261 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010262 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10263 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010264 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010265}
10266
10267// If we have 2 windows with identical timeouts that are both unresponsive,
10268// it doesn't matter which order they should have ANR.
10269// But we should receive ANR for both.
10270TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
10271 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010272 mUnfocusedWindow->setDispatchingTimeout(
10273 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010274 mDispatcher->onWindowInfosChanged(
10275 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010276
10277 tapOnFocusedWindow();
10278 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010279 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010280 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
10281 mFocusedWindow->getDispatchingTimeout(
10282 DISPATCHING_TIMEOUT)),
10283 mFakePolicy->getUnresponsiveWindowToken(0ms)};
10284
10285 ASSERT_THAT(anrConnectionTokens,
10286 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10287 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010288
10289 ASSERT_TRUE(mDispatcher->waitForIdle());
10290 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010291
10292 mFocusedWindow->consumeMotionDown();
10293 mFocusedWindow->consumeMotionUp();
10294 mUnfocusedWindow->consumeMotionOutside();
10295
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010296 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
10297 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010298
10299 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010300 ASSERT_THAT(responsiveTokens,
10301 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10302 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010303 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010304}
10305
10306// If a window is already not responding, the second tap on the same window should be ignored.
10307// We should also log an error to account for the dropped event (not tested here).
10308// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
10309TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
10310 tapOnFocusedWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010311 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010312 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010313 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010314 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010315 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010316 ASSERT_TRUE(upEventSequenceNum);
10317 const std::chrono::duration timeout =
10318 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010319 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010320
10321 // Tap once again
10322 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010323 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010324 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10325 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010326 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010327 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010328 FOCUSED_WINDOW_LOCATION));
10329 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
10330 // valid touch target
10331 mUnfocusedWindow->assertNoEvents();
10332
10333 // Consume the first tap
10334 mFocusedWindow->finishEvent(*downEventSequenceNum);
10335 mFocusedWindow->finishEvent(*upEventSequenceNum);
10336 ASSERT_TRUE(mDispatcher->waitForIdle());
10337 // The second tap did not go to the focused window
10338 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010339 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -080010340 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10341 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010342 mFakePolicy->assertNotifyAnrWasNotCalled();
10343}
10344
10345// If you tap outside of all windows, there will not be ANR
10346TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010347 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010348 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10349 ui::LogicalDisplayId::DEFAULT, LOCATION_OUTSIDE_ALL_WINDOWS));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010350 ASSERT_TRUE(mDispatcher->waitForIdle());
10351 mFakePolicy->assertNotifyAnrWasNotCalled();
10352}
10353
10354// Since the focused window is paused, tapping on it should not produce any events
10355TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
10356 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010357 mDispatcher->onWindowInfosChanged(
10358 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010359
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010360 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010361 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10362 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010363
10364 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
10365 ASSERT_TRUE(mDispatcher->waitForIdle());
10366 // Should not ANR because the window is paused, and touches shouldn't go to it
10367 mFakePolicy->assertNotifyAnrWasNotCalled();
10368
10369 mFocusedWindow->assertNoEvents();
10370 mUnfocusedWindow->assertNoEvents();
10371}
10372
10373/**
10374 * 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 -070010375 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010376 * If a different window becomes focused at this time, the key should go to that window instead.
10377 *
10378 * Warning!!!
10379 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
10380 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010381 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010382 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
10383 *
10384 * If that value changes, this test should also change.
10385 */
10386TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
10387 // Set a long ANR timeout to prevent it from triggering
10388 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010389 mDispatcher->onWindowInfosChanged(
10390 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010391
10392 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010393 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010394 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010395 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010396 ASSERT_TRUE(upSequenceNum);
10397 // Don't finish the events yet, and send a key
10398 // Injection will succeed because we will eventually give up and send the key to the focused
10399 // window even if motions are still being processed.
10400
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010401 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010402 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10403 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010404 /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010406 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010407 // and the key remains pending, waiting for the touch events to be processed.
10408 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
10409 // under the hood.
10410 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
10411 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010412
10413 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -070010414 mFocusedWindow->setFocusable(false);
10415 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010416 mDispatcher->onWindowInfosChanged(
10417 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010418 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010419
10420 // Focus events should precede the key events
10421 mUnfocusedWindow->consumeFocusEvent(true);
10422 mFocusedWindow->consumeFocusEvent(false);
10423
10424 // Finish the tap events, which should unblock dispatcher
10425 mUnfocusedWindow->finishEvent(*downSequenceNum);
10426 mUnfocusedWindow->finishEvent(*upSequenceNum);
10427
10428 // Now that all queues are cleared and no backlog in the connections, the key event
10429 // can finally go to the newly focused "mUnfocusedWindow".
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010430 mUnfocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010431 mFocusedWindow->assertNoEvents();
10432 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010433 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010434}
10435
10436// When the touch stream is split across 2 windows, and one of them does not respond,
10437// then ANR should be raised and the touch should be canceled for the unresponsive window.
10438// The other window should not be affected by that.
10439TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
10440 // Touch Window 1
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010441 mDispatcher->notifyMotion(
10442 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10443 ui::LogicalDisplayId::DEFAULT, {FOCUSED_WINDOW_LOCATION}));
10444 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010445
10446 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +000010447 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010448 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10449 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010450 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010451
10452 const std::chrono::duration timeout =
10453 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010454 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010455
10456 mUnfocusedWindow->consumeMotionDown();
10457 mFocusedWindow->consumeMotionDown();
10458 // Focused window may or may not receive ACTION_MOVE
10459 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010460 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010461 ASSERT_TRUE(moveOrCancelSequenceNum);
10462 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
10463 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -070010464 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010465 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
10466 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
10467 mFocusedWindow->consumeMotionCancel();
10468 } else {
10469 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
10470 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010471 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010472 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10473 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010474
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010475 mUnfocusedWindow->assertNoEvents();
10476 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010477 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010478}
10479
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010480/**
10481 * If we have no focused window, and a key comes in, we start the ANR timer.
10482 * The focused application should add a focused window before the timer runs out to prevent ANR.
10483 *
10484 * If the user touches another application during this time, the key should be dropped.
10485 * Next, if a new focused window comes in, without toggling the focused application,
10486 * then no ANR should occur.
10487 *
10488 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
10489 * but in some cases the policy may not update the focused application.
10490 */
10491TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
10492 std::shared_ptr<FakeApplicationHandle> focusedApplication =
10493 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -070010494 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010495 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, focusedApplication);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010496 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
10497 mFocusedWindow->setFocusable(false);
10498
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010499 mDispatcher->onWindowInfosChanged(
10500 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010501 mFocusedWindow->consumeFocusEvent(false);
10502
10503 // Send a key. The ANR timer should start because there is no focused window.
10504 // 'focusedApplication' will get blamed if this timer completes.
10505 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010506 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010507 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10508 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010509 /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +000010510 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010511 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010512
10513 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
10514 // then the injected touches won't cause the focused event to get dropped.
10515 // The dispatcher only checks for whether the queue should be pruned upon queueing.
10516 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
10517 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
10518 // For this test, it means that the key would get delivered to the window once it becomes
10519 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010520 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010521
10522 // Touch unfocused window. This should force the pending key to get dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010523 mDispatcher->notifyMotion(
10524 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10525 ui::LogicalDisplayId::DEFAULT, {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010526
10527 // We do not consume the motion right away, because that would require dispatcher to first
10528 // process (== drop) the key event, and by that time, ANR will be raised.
10529 // Set the focused window first.
10530 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010531 mDispatcher->onWindowInfosChanged(
10532 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010533 setFocusedWindow(mFocusedWindow);
10534 mFocusedWindow->consumeFocusEvent(true);
10535 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
10536 // to another application. This could be a bug / behaviour in the policy.
10537
10538 mUnfocusedWindow->consumeMotionDown();
10539
10540 ASSERT_TRUE(mDispatcher->waitForIdle());
10541 // Should not ANR because we actually have a focused window. It was just added too slowly.
10542 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
10543}
10544
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010545/**
10546 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
10547 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
10548 * dispatcher doesn't prune pointer events incorrectly.
10549 *
10550 * This test reproduces a crash in InputDispatcher.
10551 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
10552 *
10553 * Keep the currently focused application (mApplication), and have no focused window.
10554 * We set up two additional windows:
10555 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
10556 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
10557 * window. This window is not focusable, but is touchable.
10558 *
10559 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
10560 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
10561 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
10562 *
10563 * Now, we touch "Another window". This window is owned by a different application than
10564 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
10565 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
10566 * dropping the events from its queue. Ensure that no crash occurs.
10567 *
10568 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
10569 * This does not affect the test running time.
10570 */
10571TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
10572 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
10573 std::make_shared<FakeApplicationHandle>();
10574 systemUiApplication->setDispatchingTimeout(3000ms);
10575 mFakePolicy->setStaleEventTimeout(3000ms);
10576 sp<FakeWindowHandle> navigationBar =
10577 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010578 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010579 navigationBar->setFocusable(false);
10580 navigationBar->setWatchOutsideTouch(true);
10581 navigationBar->setFrame(Rect(0, 0, 100, 100));
10582
10583 mApplication->setDispatchingTimeout(3000ms);
10584 // 'mApplication' is already focused, but we call it again here to make it explicit.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010585 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010586
10587 std::shared_ptr<FakeApplicationHandle> anotherApplication =
10588 std::make_shared<FakeApplicationHandle>();
10589 sp<FakeWindowHandle> appWindow =
10590 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010591 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010592 appWindow->setFocusable(false);
10593 appWindow->setFrame(Rect(100, 100, 200, 200));
10594
10595 mDispatcher->onWindowInfosChanged(
10596 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
10597 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
10598 mFocusedWindow->consumeFocusEvent(false);
10599
10600 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
10601 // in response.
10602 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10603 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10604 .build());
10605 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10606
10607 // Key will not be sent anywhere because we have no focused window. It will remain pending.
10608 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
10609 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010610 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10611 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010612 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010613 /*allowKeyRepeat=*/false);
10614 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10615
10616 // Finish the gesture - lift up finger and inject ACTION_UP key event
10617 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10618 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10619 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010620 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0,
10621 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010622 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010623 /*allowKeyRepeat=*/false);
10624 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10625 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
10626 // getting any events yet.
10627 navigationBar->assertNoEvents();
10628
10629 // Now touch "Another window". This touch is going to a different application than the one we
10630 // are waiting for (which is 'mApplication').
10631 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
10632 // trying to be injected) and to continue processing the rest of the events in the original
10633 // order.
10634 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10635 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
10636 .build());
10637 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
10638 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
10639 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10640
10641 appWindow->assertNoEvents();
10642 navigationBar->assertNoEvents();
10643}
10644
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010645// These tests ensure we cannot send touch events to a window that's positioned behind a window
10646// that has feature NO_INPUT_CHANNEL.
10647// Layout:
10648// Top (closest to user)
10649// mNoInputWindow (above all windows)
10650// mBottomWindow
10651// Bottom (furthest from user)
10652class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
10653 virtual void SetUp() override {
10654 InputDispatcherTest::SetUp();
10655
10656 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010657 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
10658 "Window without input channel",
10659 ui::LogicalDisplayId::DEFAULT,
10660 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010661 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010662 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
10663 // It's perfectly valid for this window to not have an associated input channel
10664
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010665 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010666 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010667 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
10668
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010669 mDispatcher->onWindowInfosChanged(
10670 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010671 }
10672
10673protected:
10674 std::shared_ptr<FakeApplicationHandle> mApplication;
10675 sp<FakeWindowHandle> mNoInputWindow;
10676 sp<FakeWindowHandle> mBottomWindow;
10677};
10678
10679TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
10680 PointF touchedPoint = {10, 10};
10681
Prabir Pradhan678438e2023-04-13 19:32:51 +000010682 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010683 AINPUT_SOURCE_TOUCHSCREEN,
10684 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010685
10686 mNoInputWindow->assertNoEvents();
10687 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
10688 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
10689 // and therefore should prevent mBottomWindow from receiving touches
10690 mBottomWindow->assertNoEvents();
10691}
10692
10693/**
10694 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
10695 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
10696 */
10697TEST_F(InputDispatcherMultiWindowOcclusionTests,
10698 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010699 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
10700 "Window with input channel and NO_INPUT_CHANNEL",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010701 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010702
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010703 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010704 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010705 mDispatcher->onWindowInfosChanged(
10706 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010707
10708 PointF touchedPoint = {10, 10};
10709
Prabir Pradhan678438e2023-04-13 19:32:51 +000010710 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010711 AINPUT_SOURCE_TOUCHSCREEN,
10712 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010713
10714 mNoInputWindow->assertNoEvents();
10715 mBottomWindow->assertNoEvents();
10716}
10717
Vishnu Nair958da932020-08-21 17:12:37 -070010718class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
10719protected:
10720 std::shared_ptr<FakeApplicationHandle> mApp;
10721 sp<FakeWindowHandle> mWindow;
10722 sp<FakeWindowHandle> mMirror;
10723
10724 virtual void SetUp() override {
10725 InputDispatcherTest::SetUp();
10726 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010727 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
10728 ui::LogicalDisplayId::DEFAULT);
10729 mMirror = mWindow->clone(ui::LogicalDisplayId::DEFAULT);
10730 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Vishnu Nair958da932020-08-21 17:12:37 -070010731 mWindow->setFocusable(true);
10732 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010733 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010734 }
10735};
10736
10737TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
10738 // Request focus on a mirrored window
10739 setFocusedWindow(mMirror);
10740
10741 // window gets focused
10742 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010743 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010744 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010745 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010746}
10747
10748// A focused & mirrored window remains focused only if the window and its mirror are both
10749// focusable.
10750TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
10751 setFocusedWindow(mMirror);
10752
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010753 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -070010754 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010755 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010756 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010757 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010758 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010759 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010760 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010761
10762 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010763 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010764
10765 // window loses focus since one of the windows associated with the token in not focusable
10766 mWindow->consumeFocusEvent(false);
10767
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010768 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010769 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010770 mWindow->assertNoEvents();
10771}
10772
10773// A focused & mirrored window remains focused until the window and its mirror both become
10774// invisible.
10775TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
10776 setFocusedWindow(mMirror);
10777
10778 // window gets focused
10779 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010781 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010782 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010783 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010784 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010785 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010786
10787 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010788 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010789
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010790 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010791 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010792 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010793 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010794 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010795 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010796
10797 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010798 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010799
10800 // window loses focus only after all windows associated with the token become invisible.
10801 mWindow->consumeFocusEvent(false);
10802
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010803 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010804 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010805 mWindow->assertNoEvents();
10806}
10807
10808// A focused & mirrored window remains focused until both windows are removed.
10809TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
10810 setFocusedWindow(mMirror);
10811
10812 // window gets focused
10813 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010814 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010815 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010816 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010817 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010818 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010819 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010820
10821 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010822 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010823
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010825 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010826 mMirror->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010827 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010828 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010829 mMirror->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010830
10831 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010832 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010833 mWindow->consumeFocusEvent(false);
10834
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010835 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010836 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010837 mWindow->assertNoEvents();
10838}
10839
10840// Focus request can be pending until one window becomes visible.
10841TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
10842 // Request focus on an invisible mirror.
10843 mWindow->setVisible(false);
10844 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010845 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010846 setFocusedWindow(mMirror);
10847
10848 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010850 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010851 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -070010852
10853 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010854 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010855
10856 // window gets focused
10857 mWindow->consumeFocusEvent(true);
10858 // window gets the pending key event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010859 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -070010860}
Prabir Pradhan99987712020-11-10 18:43:05 -080010861
10862class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
10863protected:
10864 std::shared_ptr<FakeApplicationHandle> mApp;
10865 sp<FakeWindowHandle> mWindow;
10866 sp<FakeWindowHandle> mSecondWindow;
10867
10868 void SetUp() override {
10869 InputDispatcherTest::SetUp();
10870 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010871 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
10872 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080010873 mWindow->setFocusable(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010874 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
10875 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080010876 mSecondWindow->setFocusable(true);
10877
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010878 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010879 mDispatcher->onWindowInfosChanged(
10880 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -080010881
10882 setFocusedWindow(mWindow);
10883 mWindow->consumeFocusEvent(true);
10884 }
10885
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010886 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000010887 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -080010888 }
10889
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010890 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
10891 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -080010892 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +090010893 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010894 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080010895 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010896 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -080010897 }
10898};
10899
10900TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
10901 // Ensure that capture cannot be obtained for unfocused windows.
10902 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
10903 mFakePolicy->assertSetPointerCaptureNotCalled();
10904 mSecondWindow->assertNoEvents();
10905
10906 // Ensure that capture can be enabled from the focus window.
10907 requestAndVerifyPointerCapture(mWindow, true);
10908
10909 // Ensure that capture cannot be disabled from a window that does not have capture.
10910 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
10911 mFakePolicy->assertSetPointerCaptureNotCalled();
10912
10913 // Ensure that capture can be disabled from the window with capture.
10914 requestAndVerifyPointerCapture(mWindow, false);
10915}
10916
10917TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010918 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080010919
10920 setFocusedWindow(mSecondWindow);
10921
10922 // Ensure that the capture disabled event was sent first.
10923 mWindow->consumeCaptureEvent(false);
10924 mWindow->consumeFocusEvent(false);
10925 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +090010926 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080010927
10928 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010929 notifyPointerCaptureChanged({});
10930 notifyPointerCaptureChanged(request);
10931 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -080010932 mWindow->assertNoEvents();
10933 mSecondWindow->assertNoEvents();
10934 mFakePolicy->assertSetPointerCaptureNotCalled();
10935}
10936
10937TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010938 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080010939
10940 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010941 notifyPointerCaptureChanged({});
10942 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080010943
10944 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +090010945 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080010946 mWindow->consumeCaptureEvent(false);
10947 mWindow->assertNoEvents();
10948}
10949
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010950TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
10951 requestAndVerifyPointerCapture(mWindow, true);
10952
10953 // The first window loses focus.
10954 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +090010955 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010956 mWindow->consumeCaptureEvent(false);
10957
10958 // Request Pointer Capture from the second window before the notification from InputReader
10959 // arrives.
10960 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090010961 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010962
10963 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010964 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010965
10966 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010967 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080010968
10969 mSecondWindow->consumeFocusEvent(true);
10970 mSecondWindow->consumeCaptureEvent(true);
10971}
10972
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010973TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
10974 // App repeatedly enables and disables capture.
10975 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090010976 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010977 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090010978 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010979 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090010980 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000010981
10982 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
10983 // first request is now stale, this should do nothing.
10984 notifyPointerCaptureChanged(firstRequest);
10985 mWindow->assertNoEvents();
10986
10987 // InputReader notifies that the second request was enabled.
10988 notifyPointerCaptureChanged(secondRequest);
10989 mWindow->consumeCaptureEvent(true);
10990}
10991
Prabir Pradhan7092e262022-05-03 16:51:09 +000010992TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
10993 requestAndVerifyPointerCapture(mWindow, true);
10994
10995 // App toggles pointer capture off and on.
10996 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090010997 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +000010998
10999 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011000 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011001
11002 // InputReader notifies that the latest "enable" request was processed, while skipping over the
11003 // preceding "disable" request.
11004 notifyPointerCaptureChanged(enableRequest);
11005
11006 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
11007 // any notifications.
11008 mWindow->assertNoEvents();
11009}
11010
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011011/**
11012 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
11013 * mouse movements don't affect the previous mouse hovering state.
11014 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
11015 * HOVER_MOVE events).
11016 */
11017TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
11018 // Mouse hover on the window
11019 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11020 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11021 .build());
11022 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11023 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11024 .build());
11025
11026 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
11027 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
11028
11029 // Start pointer capture
11030 requestAndVerifyPointerCapture(mWindow, true);
11031
11032 // Send some relative mouse movements and receive them in the window.
11033 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
11034 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
11035 .build());
11036 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
11037 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
11038
11039 // Stop pointer capture
11040 requestAndVerifyPointerCapture(mWindow, false);
11041
11042 // Continue hovering on the window
11043 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11044 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
11045 .build());
11046 mWindow->consumeMotionEvent(
11047 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
11048
11049 mWindow->assertNoEvents();
11050}
11051
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011052TEST_F(InputDispatcherPointerCaptureTests, MultiDisplayPointerCapture) {
11053 // The default display is the focused display to begin with.
11054 requestAndVerifyPointerCapture(mWindow, true);
11055
11056 // Move the second window to a second display, make it the focused window on that display.
11057 mSecondWindow->editInfo()->displayId = SECOND_DISPLAY_ID;
11058 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11059 setFocusedWindow(mSecondWindow);
11060 mSecondWindow->consumeFocusEvent(true);
11061
11062 mWindow->assertNoEvents();
11063
11064 // The second window cannot gain capture because it is not on the focused display.
11065 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11066 mFakePolicy->assertSetPointerCaptureNotCalled();
11067 mSecondWindow->assertNoEvents();
11068
11069 // Make the second display the focused display.
11070 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +000011071 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011072
11073 // This causes the first window to lose pointer capture, and it's unable to request capture.
11074 mWindow->consumeCaptureEvent(false);
11075 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11076
11077 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11078 mFakePolicy->assertSetPointerCaptureNotCalled();
11079
11080 // The second window is now able to gain pointer capture successfully.
11081 requestAndVerifyPointerCapture(mSecondWindow, true);
11082}
11083
Hiroki Sato25040232024-02-22 17:21:22 +090011084using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
11085
11086TEST_F(InputDispatcherPointerCaptureDeathTest,
11087 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
11088 testing::GTEST_FLAG(death_test_style) = "threadsafe";
11089 ScopedSilentDeath _silentDeath;
11090
11091 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11092 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11093
11094 // Dispatch a pointer changed event with a wrong token.
11095 request.window = mSecondWindow->getToken();
11096 ASSERT_DEATH(
11097 {
11098 notifyPointerCaptureChanged(request);
11099 mSecondWindow->consumeCaptureEvent(true);
11100 },
11101 "Unexpected requested window for Pointer Capture.");
11102}
11103
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011104class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
11105protected:
11106 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000011107
11108 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
11109 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
11110
11111 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
11112 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11113
11114 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
11115 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
11116 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11117 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
11118 MAXIMUM_OBSCURING_OPACITY);
11119
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011120 static constexpr gui::Uid TOUCHED_APP_UID{10001};
11121 static constexpr gui::Uid APP_B_UID{10002};
11122 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011123
11124 sp<FakeWindowHandle> mTouchWindow;
11125
11126 virtual void SetUp() override {
11127 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011128 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011129 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
11130 }
11131
11132 virtual void TearDown() override {
11133 InputDispatcherTest::TearDown();
11134 mTouchWindow.clear();
11135 }
11136
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011137 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050011138 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011139 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011140 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011141 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011142 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011143 return window;
11144 }
11145
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011146 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011147 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
11148 sp<FakeWindowHandle> window =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011149 sp<FakeWindowHandle>::make(app, mDispatcher, name, ui::LogicalDisplayId::DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011150 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011151 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011152 return window;
11153 }
11154
11155 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011156 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011157 AINPUT_SOURCE_TOUCHSCREEN,
11158 ui::LogicalDisplayId::DEFAULT, points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011159 }
11160};
11161
11162TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011163 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011164 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011165 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011166
11167 touch();
11168
11169 mTouchWindow->assertNoEvents();
11170}
11171
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011172TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000011173 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
11174 const sp<FakeWindowHandle>& w =
11175 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011176 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011177
11178 touch();
11179
11180 mTouchWindow->assertNoEvents();
11181}
11182
11183TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011184 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
11185 const sp<FakeWindowHandle>& w =
11186 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011187 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011188
11189 touch();
11190
11191 w->assertNoEvents();
11192}
11193
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011194TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011195 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011196 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011197
11198 touch();
11199
11200 mTouchWindow->consumeAnyMotionDown();
11201}
11202
11203TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011204 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011205 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011206 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011207 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011208
11209 touch({PointF{100, 100}});
11210
11211 mTouchWindow->consumeAnyMotionDown();
11212}
11213
11214TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011215 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011216 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011217 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011218
11219 touch();
11220
11221 mTouchWindow->consumeAnyMotionDown();
11222}
11223
11224TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
11225 const sp<FakeWindowHandle>& w =
11226 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011227 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011228
11229 touch();
11230
11231 mTouchWindow->consumeAnyMotionDown();
11232}
11233
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011234TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
11235 const sp<FakeWindowHandle>& w =
11236 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011237 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011238
11239 touch();
11240
11241 w->assertNoEvents();
11242}
11243
11244/**
11245 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
11246 * inside) while letting them pass-through. Note that even though touch passes through the occluding
11247 * window, the occluding window will still receive ACTION_OUTSIDE event.
11248 */
11249TEST_F(InputDispatcherUntrustedTouchesTest,
11250 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
11251 const sp<FakeWindowHandle>& w =
11252 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011253 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011254 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011255
11256 touch();
11257
11258 w->consumeMotionOutside();
11259}
11260
11261TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
11262 const sp<FakeWindowHandle>& w =
11263 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011264 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011265 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011266
11267 touch();
11268
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011269 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011270}
11271
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011272TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011273 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011274 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11275 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011276 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011277
11278 touch();
11279
11280 mTouchWindow->consumeAnyMotionDown();
11281}
11282
11283TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
11284 const sp<FakeWindowHandle>& w =
11285 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11286 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011287 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011288
11289 touch();
11290
11291 mTouchWindow->consumeAnyMotionDown();
11292}
11293
11294TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011295 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011296 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11297 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011298 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011299
11300 touch();
11301
11302 mTouchWindow->assertNoEvents();
11303}
11304
11305TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
11306 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
11307 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011308 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11309 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011310 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011311 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11312 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011313 mDispatcher->onWindowInfosChanged(
11314 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011315
11316 touch();
11317
11318 mTouchWindow->assertNoEvents();
11319}
11320
11321TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
11322 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
11323 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011324 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11325 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011326 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011327 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11328 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011329 mDispatcher->onWindowInfosChanged(
11330 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011331
11332 touch();
11333
11334 mTouchWindow->consumeAnyMotionDown();
11335}
11336
11337TEST_F(InputDispatcherUntrustedTouchesTest,
11338 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
11339 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011340 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11341 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011342 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011343 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11344 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011345 mDispatcher->onWindowInfosChanged(
11346 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011347
11348 touch();
11349
11350 mTouchWindow->consumeAnyMotionDown();
11351}
11352
11353TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
11354 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011355 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11356 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011357 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011358 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11359 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011360 mDispatcher->onWindowInfosChanged(
11361 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011362
11363 touch();
11364
11365 mTouchWindow->assertNoEvents();
11366}
11367
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011368TEST_F(InputDispatcherUntrustedTouchesTest,
11369 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
11370 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011371 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11372 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011373 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011374 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11375 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011376 mDispatcher->onWindowInfosChanged(
11377 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011378
11379 touch();
11380
11381 mTouchWindow->assertNoEvents();
11382}
11383
11384TEST_F(InputDispatcherUntrustedTouchesTest,
11385 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
11386 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011387 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11388 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011389 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011390 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11391 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011392 mDispatcher->onWindowInfosChanged(
11393 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011394
11395 touch();
11396
11397 mTouchWindow->consumeAnyMotionDown();
11398}
11399
11400TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
11401 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011402 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11403 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011404 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011405
11406 touch();
11407
11408 mTouchWindow->consumeAnyMotionDown();
11409}
11410
11411TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
11412 const sp<FakeWindowHandle>& w =
11413 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011414 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011415
11416 touch();
11417
11418 mTouchWindow->consumeAnyMotionDown();
11419}
11420
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011421TEST_F(InputDispatcherUntrustedTouchesTest,
11422 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
11423 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11424 const sp<FakeWindowHandle>& w =
11425 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011426 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011427
11428 touch();
11429
11430 mTouchWindow->assertNoEvents();
11431}
11432
11433TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
11434 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11435 const sp<FakeWindowHandle>& w =
11436 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011437 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011438
11439 touch();
11440
11441 mTouchWindow->consumeAnyMotionDown();
11442}
11443
11444TEST_F(InputDispatcherUntrustedTouchesTest,
11445 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
11446 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
11447 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011448 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11449 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011450 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011451
11452 touch();
11453
11454 mTouchWindow->consumeAnyMotionDown();
11455}
11456
11457TEST_F(InputDispatcherUntrustedTouchesTest,
11458 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
11459 const sp<FakeWindowHandle>& w1 =
11460 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11461 OPACITY_BELOW_THRESHOLD);
11462 const sp<FakeWindowHandle>& w2 =
11463 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11464 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011465 mDispatcher->onWindowInfosChanged(
11466 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011467
11468 touch();
11469
11470 mTouchWindow->assertNoEvents();
11471}
11472
11473/**
11474 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
11475 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
11476 * (which alone would result in allowing touches) does not affect the blocking behavior.
11477 */
11478TEST_F(InputDispatcherUntrustedTouchesTest,
11479 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
11480 const sp<FakeWindowHandle>& wB =
11481 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11482 OPACITY_BELOW_THRESHOLD);
11483 const sp<FakeWindowHandle>& wC =
11484 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11485 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011486 mDispatcher->onWindowInfosChanged(
11487 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011488
11489 touch();
11490
11491 mTouchWindow->assertNoEvents();
11492}
11493
11494/**
11495 * This test is testing that a window from a different UID but with same application token doesn't
11496 * block the touch. Apps can share the application token for close UI collaboration for example.
11497 */
11498TEST_F(InputDispatcherUntrustedTouchesTest,
11499 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
11500 const sp<FakeWindowHandle>& w =
11501 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
11502 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011503 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011504
11505 touch();
11506
11507 mTouchWindow->consumeAnyMotionDown();
11508}
11509
arthurhungb89ccb02020-12-30 16:19:01 +080011510class InputDispatcherDragTests : public InputDispatcherTest {
11511protected:
11512 std::shared_ptr<FakeApplicationHandle> mApp;
11513 sp<FakeWindowHandle> mWindow;
11514 sp<FakeWindowHandle> mSecondWindow;
11515 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011516 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011517 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
11518 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080011519
11520 void SetUp() override {
11521 InputDispatcherTest::SetUp();
11522 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011523 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11524 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011525 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011526
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011527 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11528 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011529 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011530
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011531 mSpyWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow",
11532 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011533 mSpyWindow->setSpy(true);
11534 mSpyWindow->setTrustedOverlay(true);
11535 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
11536
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011537 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011538 mDispatcher->onWindowInfosChanged(
11539 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
11540 {},
11541 0,
11542 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011543 }
11544
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011545 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
11546 switch (fromSource) {
11547 case AINPUT_SOURCE_TOUCHSCREEN:
11548 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011549 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011550 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011551 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11552 break;
11553 case AINPUT_SOURCE_STYLUS:
11554 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011555 injectMotionEvent(*mDispatcher,
11556 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11557 AINPUT_SOURCE_STYLUS)
11558 .buttonState(
11559 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
11560 .pointer(PointerBuilder(0, ToolType::STYLUS)
11561 .x(50)
11562 .y(50))
11563 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011564 break;
11565 case AINPUT_SOURCE_MOUSE:
11566 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011567 injectMotionEvent(*mDispatcher,
11568 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11569 AINPUT_SOURCE_MOUSE)
11570 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
11571 .pointer(PointerBuilder(MOUSE_POINTER_ID,
11572 ToolType::MOUSE)
11573 .x(50)
11574 .y(50))
11575 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011576 break;
11577 default:
11578 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
11579 }
arthurhungb89ccb02020-12-30 16:19:01 +080011580
11581 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011582 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011583 // Spy window should also receive motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011584 mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011585 }
11586
11587 // Start performing drag, we will create a drag window and transfer touch to it.
11588 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
11589 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011590 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000011591 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011592 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000011593 }
arthurhungb89ccb02020-12-30 16:19:01 +080011594
11595 // The drag window covers the entire display
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011596 mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow",
11597 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011598 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011599 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
11600 *mWindow->getInfo(), *mSecondWindow->getInfo()},
11601 {},
11602 0,
11603 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011604
11605 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000011606 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000011607 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
11608 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000011609 if (transferred) {
11610 mWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011611 mDragWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
11612 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000011613 }
11614 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080011615 }
11616};
11617
11618TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011619 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080011620
11621 // Move on window.
11622 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011623 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011624 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011625 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011626 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11627 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011628 mWindow->consumeDragEvent(false, 50, 50);
11629 mSecondWindow->assertNoEvents();
11630
11631 // Move to another window.
11632 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011633 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011634 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011635 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011636 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11637 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011638 mWindow->consumeDragEvent(true, 150, 50);
11639 mSecondWindow->consumeDragEvent(false, 50, 50);
11640
11641 // Move back to original window.
11642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011643 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011644 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011646 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11647 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011648 mWindow->consumeDragEvent(false, 50, 50);
11649 mSecondWindow->consumeDragEvent(true, -50, 50);
11650
11651 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011652 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011653 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011654 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011655 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011656 mWindow->assertNoEvents();
11657 mSecondWindow->assertNoEvents();
11658}
11659
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011660TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011661 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011662
11663 // No cancel event after drag start
11664 mSpyWindow->assertNoEvents();
11665
11666 const MotionEvent secondFingerDownEvent =
11667 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11668 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011669 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11670 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011671 .build();
11672 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011673 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011674 InputEventInjectionSync::WAIT_FOR_RESULT))
11675 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11676
11677 // Receives cancel for first pointer after next pointer down
11678 mSpyWindow->consumeMotionCancel();
11679 mSpyWindow->consumeMotionDown();
11680
11681 mSpyWindow->assertNoEvents();
11682}
11683
arthurhungf452d0b2021-01-06 00:19:52 +080011684TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011685 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080011686
11687 // Move on window.
11688 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011689 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011690 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080011691 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011692 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11693 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080011694 mWindow->consumeDragEvent(false, 50, 50);
11695 mSecondWindow->assertNoEvents();
11696
11697 // Move to another window.
11698 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011699 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011700 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080011701 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011702 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11703 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080011704 mWindow->consumeDragEvent(true, 150, 50);
11705 mSecondWindow->consumeDragEvent(false, 50, 50);
11706
11707 // drop to another window.
11708 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011709 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080011710 {150, 50}))
11711 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011712 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011713 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080011714 mWindow->assertNoEvents();
11715 mSecondWindow->assertNoEvents();
11716}
11717
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011718TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
11719 startDrag();
11720
11721 // No cancel event after drag start
11722 mSpyWindow->assertNoEvents();
11723
11724 const MotionEvent secondFingerDownEvent =
11725 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11726 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
11727 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11728 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
11729 .build();
11730 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11731 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
11732 InputEventInjectionSync::WAIT_FOR_RESULT))
11733 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11734
11735 // Receives cancel for first pointer after next pointer down
11736 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080011737 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011738 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
11739
11740 mSpyWindow->assertNoEvents();
11741
11742 // Spy window calls pilfer pointers
11743 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
11744 mDragWindow->assertNoEvents();
11745
11746 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080011747 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011748 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
11749 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
11750 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
11751 .build();
11752 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080011753 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011754 InputEventInjectionSync::WAIT_FOR_RESULT))
11755 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11756
11757 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000011758 mDragWindow->consumeMotionEvent(
11759 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011760 mDragWindow->assertNoEvents();
11761}
11762
arthurhung6d4bed92021-03-17 11:59:33 +080011763TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011764 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080011765
11766 // Move on window and keep button pressed.
11767 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011768 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011769 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11770 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011771 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011772 .build()))
11773 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011774 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11775 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011776 mWindow->consumeDragEvent(false, 50, 50);
11777 mSecondWindow->assertNoEvents();
11778
11779 // Move to another window and release button, expect to drop item.
11780 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011781 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011782 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11783 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011784 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011785 .build()))
11786 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011787 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11788 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011789 mWindow->assertNoEvents();
11790 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011791 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080011792
11793 // nothing to the window.
11794 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011795 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011796 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
11797 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011798 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011799 .build()))
11800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011801 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011802 mWindow->assertNoEvents();
11803 mSecondWindow->assertNoEvents();
11804}
11805
Arthur Hung54745652022-04-20 07:17:41 +000011806TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011807 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080011808
11809 // Set second window invisible.
11810 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011811 mDispatcher->onWindowInfosChanged(
11812 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080011813
11814 // Move on window.
11815 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011816 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011817 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080011818 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011819 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11820 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011821 mWindow->consumeDragEvent(false, 50, 50);
11822 mSecondWindow->assertNoEvents();
11823
11824 // Move to another window.
11825 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011826 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011827 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080011828 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011829 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11830 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011831 mWindow->consumeDragEvent(true, 150, 50);
11832 mSecondWindow->assertNoEvents();
11833
11834 // drop to another window.
11835 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011836 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080011837 {150, 50}))
11838 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011839 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011840 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011841 mWindow->assertNoEvents();
11842 mSecondWindow->assertNoEvents();
11843}
11844
Arthur Hung54745652022-04-20 07:17:41 +000011845TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011846 // Ensure window could track pointerIds if it didn't support split touch.
11847 mWindow->setPreventSplitting(true);
11848
Arthur Hung54745652022-04-20 07:17:41 +000011849 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011850 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11851 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000011852 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011853 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011854
11855 const MotionEvent secondFingerDownEvent =
11856 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011857 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000011858 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011859 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11860 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000011861 .build();
11862 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011863 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000011864 InputEventInjectionSync::WAIT_FOR_RESULT))
11865 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000011866 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000011867
11868 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011869 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000011870}
11871
11872TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
11873 // First down on second window.
11874 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011875 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
11876 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000011877 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11878
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011879 mSecondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011880
11881 // Second down on first window.
11882 const MotionEvent secondFingerDownEvent =
11883 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011884 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000011885 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011886 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
11887 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000011888 .build();
11889 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011890 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000011891 InputEventInjectionSync::WAIT_FOR_RESULT))
11892 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011893 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
11894 mSecondWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011895
11896 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011897 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000011898
11899 // Move on window.
11900 const MotionEvent secondFingerMoveEvent =
11901 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
11902 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011903 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
11904 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000011905 .build();
11906 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011907 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000011908 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011909 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11910 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000011911 mWindow->consumeDragEvent(false, 50, 50);
11912 mSecondWindow->consumeMotionMove();
11913
11914 // Release the drag pointer should perform drop.
11915 const MotionEvent secondFingerUpEvent =
11916 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
11917 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011918 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
11919 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000011920 .build();
11921 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011922 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000011923 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011924 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011925 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000011926 mWindow->assertNoEvents();
11927 mSecondWindow->consumeMotionMove();
11928}
11929
Arthur Hung3915c1f2022-05-31 07:17:17 +000011930TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011931 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000011932
11933 // Update window of second display.
11934 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070011935 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011936 mDispatcher->onWindowInfosChanged(
11937 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
11938 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
11939 {},
11940 0,
11941 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000011942
11943 // Let second display has a touch state.
11944 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011945 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000011946 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11947 AINPUT_SOURCE_TOUCHSCREEN)
11948 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011949 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000011950 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000011951 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000011952 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011953 mDispatcher->onWindowInfosChanged(
11954 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
11955 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
11956 {},
11957 0,
11958 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000011959
11960 // Move on window.
11961 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011962 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011963 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000011964 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011965 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11966 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000011967 mWindow->consumeDragEvent(false, 50, 50);
11968 mSecondWindow->assertNoEvents();
11969
11970 // Move to another window.
11971 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011972 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011973 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000011974 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011975 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11976 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000011977 mWindow->consumeDragEvent(true, 150, 50);
11978 mSecondWindow->consumeDragEvent(false, 50, 50);
11979
11980 // drop to another window.
11981 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011982 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000011983 {150, 50}))
11984 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011985 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011986 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000011987 mWindow->assertNoEvents();
11988 mSecondWindow->assertNoEvents();
11989}
11990
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011991TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
11992 startDrag(true, AINPUT_SOURCE_MOUSE);
11993 // Move on window.
11994 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011995 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011996 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
11997 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011998 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011999 .x(50)
12000 .y(50))
12001 .build()))
12002 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012003 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12004 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012005 mWindow->consumeDragEvent(false, 50, 50);
12006 mSecondWindow->assertNoEvents();
12007
12008 // Move to another window.
12009 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012010 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012011 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12012 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012013 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012014 .x(150)
12015 .y(50))
12016 .build()))
12017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012018 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12019 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012020 mWindow->consumeDragEvent(true, 150, 50);
12021 mSecondWindow->consumeDragEvent(false, 50, 50);
12022
12023 // drop to another window.
12024 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012025 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012026 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
12027 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012028 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012029 .x(150)
12030 .y(50))
12031 .build()))
12032 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012033 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012034 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012035 mWindow->assertNoEvents();
12036 mSecondWindow->assertNoEvents();
12037}
12038
Linnan Li5af92f92023-07-14 14:36:22 +080012039/**
12040 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
12041 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
12042 */
12043TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
12044 // Down on second window
12045 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012046 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12047 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012048 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12049
12050 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
12051 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
12052
12053 // Down on first window
12054 const MotionEvent secondFingerDownEvent =
12055 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012056 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012057 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12058 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12059 .build();
12060 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12061 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12062 InputEventInjectionSync::WAIT_FOR_RESULT))
12063 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12064 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12065 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
12066 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
12067
12068 // Start drag on first window
12069 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
12070
12071 // Trigger cancel
12072 mDispatcher->cancelCurrentTouch();
12073 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012074 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +000012075 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080012076 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
12077
12078 ASSERT_TRUE(mDispatcher->waitForIdle());
12079 // The D&D finished with nullptr
12080 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
12081
12082 // Remove drag window
12083 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
12084
12085 // Inject a simple gesture, ensure dispatcher not crashed
12086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012087 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12088 ui::LogicalDisplayId::DEFAULT, PointF{50, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012089 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12090 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12091
12092 const MotionEvent moveEvent =
12093 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012094 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012095 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12096 .build();
12097 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12098 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
12099 InputEventInjectionSync::WAIT_FOR_RESULT))
12100 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12101 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
12102
12103 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012104 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Li5af92f92023-07-14 14:36:22 +080012105 {50, 50}))
12106 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12107 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
12108}
12109
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012110TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
12111 // Start hovering over the window.
12112 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12113 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012114 ui::LogicalDisplayId::DEFAULT, {50, 50}));
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012115
12116 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12117 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12118
12119 ASSERT_FALSE(startDrag(/*sendDown=*/false))
12120 << "Drag and drop should not work with a hovering pointer";
12121}
12122
Vishnu Nair062a8672021-09-03 16:07:44 -070012123class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
12124
12125TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
12126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012127 sp<FakeWindowHandle> window =
12128 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12129 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012130 window->setDropInput(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012131 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012132 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012133 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012134 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012135 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012136
12137 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012138 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012139 window->assertNoEvents();
12140
Prabir Pradhan678438e2023-04-13 19:32:51 +000012141 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012142 AINPUT_SOURCE_TOUCHSCREEN,
12143 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012144 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012145 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080012146 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070012147 window->assertNoEvents();
12148
12149 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012150 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012151 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012152
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012153 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12154 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012155
Prabir Pradhan678438e2023-04-13 19:32:51 +000012156 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012157 AINPUT_SOURCE_TOUCHSCREEN,
12158 ui::LogicalDisplayId::DEFAULT));
12159 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012160 window->assertNoEvents();
12161}
12162
12163TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
12164 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12165 std::make_shared<FakeApplicationHandle>();
12166 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012167 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012168 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012169 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012170 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012171 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012172 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012173 sp<FakeWindowHandle> window =
12174 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12175 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012176 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012177 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012178 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012179 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012180 mDispatcher->onWindowInfosChanged(
12181 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012182 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012183 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012184
12185 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012186 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012187 window->assertNoEvents();
12188
Prabir Pradhan678438e2023-04-13 19:32:51 +000012189 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012190 AINPUT_SOURCE_TOUCHSCREEN,
12191 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012192 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012193 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012194 window->assertNoEvents();
12195
12196 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012197 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012198 mDispatcher->onWindowInfosChanged(
12199 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012200
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012201 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12202 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012203
Prabir Pradhan678438e2023-04-13 19:32:51 +000012204 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012205 AINPUT_SOURCE_TOUCHSCREEN,
12206 ui::LogicalDisplayId::DEFAULT));
12207 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
12208 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Vishnu Nair062a8672021-09-03 16:07:44 -070012209 window->assertNoEvents();
12210}
12211
12212TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
12213 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12214 std::make_shared<FakeApplicationHandle>();
12215 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012216 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012217 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012218 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012219 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012220 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012221 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012222 sp<FakeWindowHandle> window =
12223 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12224 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012225 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012226 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012227 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012228 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012229 mDispatcher->onWindowInfosChanged(
12230 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012231 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012232 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012233
12234 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012235 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012236 window->assertNoEvents();
12237
Prabir Pradhan678438e2023-04-13 19:32:51 +000012238 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012239 AINPUT_SOURCE_TOUCHSCREEN,
12240 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012241 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012242 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012243 window->assertNoEvents();
12244
12245 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012246 mDispatcher->onWindowInfosChanged(
12247 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012248
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012249 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12250 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012251
Prabir Pradhan678438e2023-04-13 19:32:51 +000012252 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012253 AINPUT_SOURCE_TOUCHSCREEN,
12254 ui::LogicalDisplayId::DEFAULT));
12255 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012256 window->assertNoEvents();
12257}
12258
Antonio Kantekf16f2832021-09-28 04:39:20 +000012259class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
12260protected:
12261 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000012262 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012263 sp<FakeWindowHandle> mWindow;
12264 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000012265 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012266
12267 void SetUp() override {
12268 InputDispatcherTest::SetUp();
12269
12270 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000012271 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012272 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
12273 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012274 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012275 setFocusedWindow(mWindow);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012276 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
12277 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012278 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000012279 mThirdWindow =
12280 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
12281 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
12282 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012283
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012284 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012285 mDispatcher->onWindowInfosChanged(
12286 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
12287 {},
12288 0,
12289 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000012290 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012291 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012292
Antonio Kantek15beb512022-06-13 22:35:41 +000012293 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012294 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012295 WINDOW_UID, /*hasPermission=*/true,
12296 ui::LogicalDisplayId::DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070012297 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
12298 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012299 mThirdWindow->assertNoEvents();
12300 }
12301
12302 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
12303 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000012304 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000012305 SECOND_DISPLAY_ID)) {
12306 mWindow->assertNoEvents();
12307 mSecondWindow->assertNoEvents();
12308 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070012309 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000012310 }
12311
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012312 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000012313 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070012314 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012315 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012316 mWindow->consumeTouchModeEvent(inTouchMode);
12317 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012318 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000012319 }
12320};
12321
Antonio Kantek26defcf2022-02-08 01:12:27 +000012322TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012323 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000012324 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
12325 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012326 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012327}
12328
Antonio Kantek26defcf2022-02-08 01:12:27 +000012329TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
12330 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012331 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012332 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012333 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012334 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012335 ownerUid, /*hasPermission=*/false,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012336 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000012337 mWindow->assertNoEvents();
12338 mSecondWindow->assertNoEvents();
12339}
12340
12341TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
12342 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012343 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012344 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012345 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000012346 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012347 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012348}
12349
Antonio Kantekf16f2832021-09-28 04:39:20 +000012350TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012351 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000012352 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
12353 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012354 /*hasPermission=*/true,
12355 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012356 mWindow->assertNoEvents();
12357 mSecondWindow->assertNoEvents();
12358}
12359
Antonio Kantek15beb512022-06-13 22:35:41 +000012360TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
12361 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
12362 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12363 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012364 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000012365 mWindow->assertNoEvents();
12366 mSecondWindow->assertNoEvents();
12367 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
12368}
12369
Antonio Kantek48710e42022-03-24 14:19:30 -070012370TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
12371 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012372 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012373 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070012374 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012375 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Antonio Kantek48710e42022-03-24 14:19:30 -070012376
12377 // Then remove focus.
12378 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012379 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070012380
12381 // Assert that caller can switch touch mode by owning one of the last interacted window.
12382 const WindowInfo& windowInfo = *mWindow->getInfo();
12383 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12384 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012385 /*hasPermission=*/false,
12386 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070012387}
12388
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012389class InputDispatcherSpyWindowTest : public InputDispatcherTest {
12390public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012391 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012392 std::shared_ptr<FakeApplicationHandle> application =
12393 std::make_shared<FakeApplicationHandle>();
12394 std::string name = "Fake Spy ";
12395 name += std::to_string(mSpyCount++);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012396 sp<FakeWindowHandle> spy =
12397 sp<FakeWindowHandle>::make(application, mDispatcher, name.c_str(),
12398 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012399 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012400 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012401 return spy;
12402 }
12403
12404 sp<FakeWindowHandle> createForeground() {
12405 std::shared_ptr<FakeApplicationHandle> application =
12406 std::make_shared<FakeApplicationHandle>();
12407 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012408 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012409 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012410 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012411 return window;
12412 }
12413
12414private:
12415 int mSpyCount{0};
12416};
12417
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012418using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012419/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012420 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
12421 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012422TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070012423 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012424 ScopedSilentDeath _silentDeath;
12425
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012426 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012427 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012428 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012429 ".* not a trusted overlay");
12430}
12431
12432/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012433 * Input injection into a display with a spy window but no foreground windows should succeed.
12434 */
12435TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012436 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012437 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012438
12439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012440 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12441 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012442 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012443 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012444}
12445
12446/**
12447 * Verify the order in which different input windows receive events. The touched foreground window
12448 * (if there is one) should always receive the event first. When there are multiple spy windows, the
12449 * spy windows will receive the event according to their Z-order, where the top-most spy window will
12450 * receive events before ones belows it.
12451 *
12452 * Here, we set up a scenario with four windows in the following Z order from the top:
12453 * spy1, spy2, window, spy3.
12454 * We then inject an event and verify that the foreground "window" receives it first, followed by
12455 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
12456 * window.
12457 */
12458TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
12459 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012460 auto spy1 = createSpy();
12461 auto spy2 = createSpy();
12462 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012463 mDispatcher->onWindowInfosChanged(
12464 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012465 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
12466 const size_t numChannels = channels.size();
12467
Michael Wright8e9a8562022-02-09 13:44:29 +000012468 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012469 if (!epollFd.ok()) {
12470 FAIL() << "Failed to create epoll fd";
12471 }
12472
12473 for (size_t i = 0; i < numChannels; i++) {
12474 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
12475 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
12476 FAIL() << "Failed to add fd to epoll";
12477 }
12478 }
12479
12480 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012481 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12482 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012483 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12484
12485 std::vector<size_t> eventOrder;
12486 std::vector<struct epoll_event> events(numChannels);
12487 for (;;) {
12488 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
12489 (100ms).count());
12490 if (nFds < 0) {
12491 FAIL() << "Failed to call epoll_wait";
12492 }
12493 if (nFds == 0) {
12494 break; // epoll_wait timed out
12495 }
12496 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070012497 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070012498 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012499 channels[i]->consumeMotionDown();
12500 }
12501 }
12502
12503 // Verify the order in which the events were received.
12504 EXPECT_EQ(3u, eventOrder.size());
12505 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
12506 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
12507 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
12508}
12509
12510/**
12511 * A spy window using the NOT_TOUCHABLE flag does not receive events.
12512 */
12513TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
12514 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012515 auto spy = createSpy();
12516 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012517 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012518
12519 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012520 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12521 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012522 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012523 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012524 spy->assertNoEvents();
12525}
12526
12527/**
12528 * A spy window will only receive gestures that originate within its touchable region. Gestures that
12529 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
12530 * to the window.
12531 */
12532TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
12533 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012534 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012535 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012536 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012537
12538 // Inject an event outside the spy window's touchable region.
12539 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012540 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12541 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012542 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12543 window->consumeMotionDown();
12544 spy->assertNoEvents();
12545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012546 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12547 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012548 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12549 window->consumeMotionUp();
12550 spy->assertNoEvents();
12551
12552 // Inject an event inside the spy window's touchable region.
12553 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012554 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12555 ui::LogicalDisplayId::DEFAULT, {5, 10}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012556 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12557 window->consumeMotionDown();
12558 spy->consumeMotionDown();
12559}
12560
12561/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012562 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012563 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012564 */
12565TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
12566 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012567 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012568 auto spy = createSpy();
12569 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012570 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012571 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012572 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012573
12574 // Inject an event outside the spy window's frame and touchable region.
12575 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012576 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12577 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012578 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12579 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012580 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012581}
12582
12583/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012584 * Even when a spy window spans over multiple foreground windows, the spy should receive all
12585 * pointers that are down within its bounds.
12586 */
12587TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
12588 auto windowLeft = createForeground();
12589 windowLeft->setFrame({0, 0, 100, 200});
12590 auto windowRight = createForeground();
12591 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012592 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012593 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012594 mDispatcher->onWindowInfosChanged(
12595 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012596
12597 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012598 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12599 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012600 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12601 windowLeft->consumeMotionDown();
12602 spy->consumeMotionDown();
12603
12604 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012605 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012606 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012607 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12608 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012609 .build();
12610 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012611 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012612 InputEventInjectionSync::WAIT_FOR_RESULT))
12613 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12614 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000012615 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012616}
12617
12618/**
12619 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
12620 * the spy should receive the second pointer with ACTION_DOWN.
12621 */
12622TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
12623 auto window = createForeground();
12624 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012625 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012626 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012627 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012628
12629 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012630 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12631 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012632 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12633 window->consumeMotionDown();
12634 spyRight->assertNoEvents();
12635
12636 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012637 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012638 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012639 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12640 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012641 .build();
12642 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012643 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012644 InputEventInjectionSync::WAIT_FOR_RESULT))
12645 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000012646 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012647 spyRight->consumeMotionDown();
12648}
12649
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012650/**
12651 * The spy window should not be able to affect whether or not touches are split. Only the foreground
12652 * windows should be allowed to control split touch.
12653 */
12654TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080012655 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012656 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012657 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080012658 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012659
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012660 auto window = createForeground();
12661 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012662
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012663 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012664
12665 // First finger down, no window touched.
12666 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012667 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12668 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012669 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012670 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012671 window->assertNoEvents();
12672
12673 // Second finger down on window, the window should receive touch down.
12674 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012675 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012676 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012677 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012678 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12679 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012680 .build();
12681 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012682 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012683 InputEventInjectionSync::WAIT_FOR_RESULT))
12684 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12685
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012686 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000012687 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012688}
12689
12690/**
12691 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
12692 * do not receive key events.
12693 */
12694TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012695 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012696 spy->setFocusable(false);
12697
12698 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012699 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012700 setFocusedWindow(window);
12701 window->consumeFocusEvent(true);
12702
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012704 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012705 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012706
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012708 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012709 window->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012710
12711 spy->assertNoEvents();
12712}
12713
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012714using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
12715
12716/**
12717 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
12718 * are currently sent to any other windows - including other spy windows - will also be cancelled.
12719 */
12720TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
12721 auto window = createForeground();
12722 auto spy1 = createSpy();
12723 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012724 mDispatcher->onWindowInfosChanged(
12725 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012726
12727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012728 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12729 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012730 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12731 window->consumeMotionDown();
12732 spy1->consumeMotionDown();
12733 spy2->consumeMotionDown();
12734
12735 // Pilfer pointers from the second spy window.
12736 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
12737 spy2->assertNoEvents();
12738 spy1->consumeMotionCancel();
12739 window->consumeMotionCancel();
12740
12741 // The rest of the gesture should only be sent to the second spy window.
12742 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012743 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012744 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012745 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12746 spy2->consumeMotionMove();
12747 spy1->assertNoEvents();
12748 window->assertNoEvents();
12749}
12750
12751/**
12752 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
12753 * in the middle of the gesture.
12754 */
12755TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
12756 auto window = createForeground();
12757 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012758 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012759
12760 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012761 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12762 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012763 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012764 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12765 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012766
12767 window->releaseChannel();
12768
12769 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
12770
12771 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012772 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12773 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012774 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012775 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012776}
12777
12778/**
12779 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
12780 * the spy, but not to any other windows.
12781 */
12782TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
12783 auto spy = createSpy();
12784 auto window = createForeground();
12785
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012786 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012787
12788 // First finger down on the window and the spy.
12789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012790 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12791 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012792 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12793 spy->consumeMotionDown();
12794 window->consumeMotionDown();
12795
12796 // Spy window pilfers the pointers.
12797 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
12798 window->consumeMotionCancel();
12799
12800 // Second finger down on the window and spy, but the window should not receive the pointer down.
12801 const MotionEvent secondFingerDownEvent =
12802 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012803 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012804 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012805 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12806 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012807 .build();
12808 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012809 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012810 InputEventInjectionSync::WAIT_FOR_RESULT))
12811 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12812
Harry Cutts33476232023-01-30 19:57:29 +000012813 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012814
12815 // Third finger goes down outside all windows, so injection should fail.
12816 const MotionEvent thirdFingerDownEvent =
12817 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012818 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012819 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012820 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12821 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12822 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012823 .build();
12824 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012825 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012826 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080012827 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012828
12829 spy->assertNoEvents();
12830 window->assertNoEvents();
12831}
12832
12833/**
12834 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
12835 */
12836TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
12837 auto spy = createSpy();
12838 spy->setFrame(Rect(0, 0, 100, 100));
12839 auto window = createForeground();
12840 window->setFrame(Rect(0, 0, 200, 200));
12841
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012842 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012843
12844 // First finger down on the window only
12845 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012846 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12847 ui::LogicalDisplayId::DEFAULT, {150, 150}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012848 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12849 window->consumeMotionDown();
12850
12851 // Second finger down on the spy and window
12852 const MotionEvent secondFingerDownEvent =
12853 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012854 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012855 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012856 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
12857 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012858 .build();
12859 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012860 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012861 InputEventInjectionSync::WAIT_FOR_RESULT))
12862 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12863 spy->consumeMotionDown();
12864 window->consumeMotionPointerDown(1);
12865
12866 // Third finger down on the spy and window
12867 const MotionEvent thirdFingerDownEvent =
12868 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012869 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012870 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012871 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
12872 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
12873 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012874 .build();
12875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012876 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012877 InputEventInjectionSync::WAIT_FOR_RESULT))
12878 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12879 spy->consumeMotionPointerDown(1);
12880 window->consumeMotionPointerDown(2);
12881
12882 // Spy window pilfers the pointers.
12883 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012884 window->consumeMotionPointerUp(/*idx=*/2, ui::LogicalDisplayId::DEFAULT,
12885 AMOTION_EVENT_FLAG_CANCELED);
12886 window->consumeMotionPointerUp(/*idx=*/1, ui::LogicalDisplayId::DEFAULT,
12887 AMOTION_EVENT_FLAG_CANCELED);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012888
12889 spy->assertNoEvents();
12890 window->assertNoEvents();
12891}
12892
12893/**
12894 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
12895 * other windows should be canceled. If this results in the cancellation of all pointers for some
12896 * window, then that window should receive ACTION_CANCEL.
12897 */
12898TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
12899 auto spy = createSpy();
12900 spy->setFrame(Rect(0, 0, 100, 100));
12901 auto window = createForeground();
12902 window->setFrame(Rect(0, 0, 200, 200));
12903
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012904 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012905
12906 // First finger down on both spy and window
12907 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012908 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12909 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012910 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12911 window->consumeMotionDown();
12912 spy->consumeMotionDown();
12913
12914 // Second finger down on the spy and window
12915 const MotionEvent secondFingerDownEvent =
12916 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012917 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012918 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012919 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
12920 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012921 .build();
12922 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012923 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012924 InputEventInjectionSync::WAIT_FOR_RESULT))
12925 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12926 spy->consumeMotionPointerDown(1);
12927 window->consumeMotionPointerDown(1);
12928
12929 // Spy window pilfers the pointers.
12930 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
12931 window->consumeMotionCancel();
12932
12933 spy->assertNoEvents();
12934 window->assertNoEvents();
12935}
12936
12937/**
12938 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
12939 * be sent to other windows
12940 */
12941TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
12942 auto spy = createSpy();
12943 spy->setFrame(Rect(0, 0, 100, 100));
12944 auto window = createForeground();
12945 window->setFrame(Rect(0, 0, 200, 200));
12946
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012947 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012948
12949 // First finger down on both window and spy
12950 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012951 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12952 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012953 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12954 window->consumeMotionDown();
12955 spy->consumeMotionDown();
12956
12957 // Spy window pilfers the pointers.
12958 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
12959 window->consumeMotionCancel();
12960
12961 // Second finger down on the window only
12962 const MotionEvent secondFingerDownEvent =
12963 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012964 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012965 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012966 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
12967 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012968 .build();
12969 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012970 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012971 InputEventInjectionSync::WAIT_FOR_RESULT))
12972 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12973 window->consumeMotionDown();
12974 window->assertNoEvents();
12975
12976 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
12977 spy->consumeMotionMove();
12978 spy->assertNoEvents();
12979}
12980
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070012981/**
12982 * A window on the left and a window on the right. Also, a spy window that's above all of the
12983 * windows, and spanning both left and right windows.
12984 * Send simultaneous motion streams from two different devices, one to the left window, and another
12985 * to the right window.
12986 * Pilfer from spy window.
12987 * Check that the pilfering only affects the pointers that are actually being received by the spy.
12988 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070012989TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer_legacy) {
12990 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070012991 sp<FakeWindowHandle> spy = createSpy();
12992 spy->setFrame(Rect(0, 0, 200, 200));
12993 sp<FakeWindowHandle> leftWindow = createForeground();
12994 leftWindow->setFrame(Rect(0, 0, 100, 100));
12995
12996 sp<FakeWindowHandle> rightWindow = createForeground();
12997 rightWindow->setFrame(Rect(100, 0, 200, 100));
12998
12999 constexpr int32_t stylusDeviceId = 1;
13000 constexpr int32_t touchDeviceId = 2;
13001
13002 mDispatcher->onWindowInfosChanged(
13003 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13004
13005 // Stylus down on left window and spy
13006 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13007 .deviceId(stylusDeviceId)
13008 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13009 .build());
13010 leftWindow->consumeMotionEvent(
13011 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13012 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13013
13014 // Finger down on right window and spy - but spy already has stylus
13015 mDispatcher->notifyMotion(
13016 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13017 .deviceId(touchDeviceId)
13018 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13019 .build());
13020 rightWindow->consumeMotionEvent(
13021 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013022 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013023
13024 // Act: pilfer from spy. Spy is currently receiving touch events.
13025 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013026 leftWindow->consumeMotionEvent(
13027 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013028 rightWindow->consumeMotionEvent(
13029 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13030
13031 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
13032 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13033 .deviceId(stylusDeviceId)
13034 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13035 .build());
13036 mDispatcher->notifyMotion(
13037 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13038 .deviceId(touchDeviceId)
13039 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13040 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013041 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013042
13043 spy->assertNoEvents();
13044 leftWindow->assertNoEvents();
13045 rightWindow->assertNoEvents();
13046}
13047
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013048/**
13049 * A window on the left and a window on the right. Also, a spy window that's above all of the
13050 * windows, and spanning both left and right windows.
13051 * Send simultaneous motion streams from two different devices, one to the left window, and another
13052 * to the right window.
13053 * Pilfer from spy window.
13054 * Check that the pilfering affects all of the pointers that are actually being received by the spy.
13055 * The spy should receive both the touch and the stylus events after pilfer.
13056 */
13057TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
13058 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13059 sp<FakeWindowHandle> spy = createSpy();
13060 spy->setFrame(Rect(0, 0, 200, 200));
13061 sp<FakeWindowHandle> leftWindow = createForeground();
13062 leftWindow->setFrame(Rect(0, 0, 100, 100));
13063
13064 sp<FakeWindowHandle> rightWindow = createForeground();
13065 rightWindow->setFrame(Rect(100, 0, 200, 100));
13066
13067 constexpr int32_t stylusDeviceId = 1;
13068 constexpr int32_t touchDeviceId = 2;
13069
13070 mDispatcher->onWindowInfosChanged(
13071 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13072
13073 // Stylus down on left window and spy
13074 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13075 .deviceId(stylusDeviceId)
13076 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13077 .build());
13078 leftWindow->consumeMotionEvent(
13079 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13080 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13081
13082 // Finger down on right window and spy
13083 mDispatcher->notifyMotion(
13084 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13085 .deviceId(touchDeviceId)
13086 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13087 .build());
13088 rightWindow->consumeMotionEvent(
13089 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13090 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13091
13092 // Act: pilfer from spy. Spy is currently receiving touch events.
13093 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13094 leftWindow->consumeMotionEvent(
13095 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
13096 rightWindow->consumeMotionEvent(
13097 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13098
13099 // Continue movements from both stylus and touch. Touch and stylus will be delivered to spy
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013100 // Instead of sending the two MOVE events for each input device together, and then receiving
13101 // them both, process them one at at time. InputConsumer is always in the batching mode, which
13102 // means that the two MOVE events will be initially put into a batch. Once the events are
13103 // batched, the 'consume' call may result in any of the MOVE events to be sent first (depending
13104 // on the implementation of InputConsumer), which would mean that the order of the received
13105 // events could be different depending on whether there are 1 or 2 events pending in the
13106 // InputChannel at the time the test calls 'consume'. To make assertions simpler here, and to
13107 // avoid this confusing behaviour, send and receive each MOVE event separately.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013108 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13109 .deviceId(stylusDeviceId)
13110 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13111 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013112 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013113 mDispatcher->notifyMotion(
13114 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13115 .deviceId(touchDeviceId)
13116 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13117 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013118 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013119
13120 spy->assertNoEvents();
13121 leftWindow->assertNoEvents();
13122 rightWindow->assertNoEvents();
13123}
13124
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000013125TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
13126 auto window = createForeground();
13127 auto spy = createSpy();
13128 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13129
13130 mDispatcher->notifyMotion(
13131 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
13132 .deviceId(1)
13133 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
13134 .build());
13135 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13136 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13137
13138 // Pilfer pointers from the spy window should fail.
13139 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
13140 spy->assertNoEvents();
13141 window->assertNoEvents();
13142}
13143
Prabir Pradhand65552b2021-10-07 11:23:50 -070013144class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
13145public:
13146 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
13147 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13148 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013149 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
13150 "Stylus interceptor window",
13151 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013152 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013153 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013154 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013155 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013156 overlay->setTrustedOverlay(true);
13157
13158 std::shared_ptr<FakeApplicationHandle> application =
13159 std::make_shared<FakeApplicationHandle>();
13160 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013161 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013162 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013163 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013164 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013165
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013166 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013167 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013168 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013169 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013170 return {std::move(overlay), std::move(window)};
13171 }
13172
13173 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000013174 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070013175 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013176 ui::LogicalDisplayId::DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070013177 }
13178
13179 void sendStylusEvent(int32_t action) {
13180 NotifyMotionArgs motionArgs =
13181 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013182 ui::LogicalDisplayId::DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013183 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000013184 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013185 }
13186};
13187
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013188using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
13189
13190TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070013191 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013192 ScopedSilentDeath _silentDeath;
13193
Prabir Pradhand65552b2021-10-07 11:23:50 -070013194 auto [overlay, window] = setupStylusOverlayScenario();
13195 overlay->setTrustedOverlay(false);
13196 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013197 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
13198 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070013199 ".* not a trusted overlay");
13200}
13201
13202TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
13203 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013204 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013205
13206 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13207 overlay->consumeMotionDown();
13208 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13209 overlay->consumeMotionUp();
13210
13211 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13212 window->consumeMotionDown();
13213 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13214 window->consumeMotionUp();
13215
13216 overlay->assertNoEvents();
13217 window->assertNoEvents();
13218}
13219
13220TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
13221 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013222 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013223 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013224
13225 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13226 overlay->consumeMotionDown();
13227 window->consumeMotionDown();
13228 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13229 overlay->consumeMotionUp();
13230 window->consumeMotionUp();
13231
13232 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13233 window->consumeMotionDown();
13234 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13235 window->consumeMotionUp();
13236
13237 overlay->assertNoEvents();
13238 window->assertNoEvents();
13239}
13240
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013241/**
13242 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
13243 * The scenario is as follows:
13244 * - The stylus interceptor overlay is configured as a spy window.
13245 * - The stylus interceptor spy receives the start of a new stylus gesture.
13246 * - It pilfers pointers and then configures itself to no longer be a spy.
13247 * - The stylus interceptor continues to receive the rest of the gesture.
13248 */
13249TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
13250 auto [overlay, window] = setupStylusOverlayScenario();
13251 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013252 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013253
13254 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13255 overlay->consumeMotionDown();
13256 window->consumeMotionDown();
13257
13258 // The interceptor pilfers the pointers.
13259 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
13260 window->consumeMotionCancel();
13261
13262 // The interceptor configures itself so that it is no longer a spy.
13263 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013264 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013265
13266 // It continues to receive the rest of the stylus gesture.
13267 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
13268 overlay->consumeMotionMove();
13269 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13270 overlay->consumeMotionUp();
13271
13272 window->assertNoEvents();
13273}
13274
Prabir Pradhan5735a322022-04-11 17:23:34 +000013275struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013276 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013277 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000013278 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
13279 std::unique_ptr<InputDispatcher>& mDispatcher;
13280
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013281 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000013282 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
13283
13284 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013285 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013286 ui::LogicalDisplayId::DEFAULT, {100, 200},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013287 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
13288 AMOTION_EVENT_INVALID_CURSOR_POSITION},
13289 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
13290 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
13291 }
13292
13293 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Linnan Li13bf76a2024-05-05 19:18:02 +080013294 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013295 ui::LogicalDisplayId::INVALID,
Prabir Pradhan5735a322022-04-11 17:23:34 +000013296 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000013297 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013298 mPolicyFlags);
13299 }
13300
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013301 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000013302 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13303 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013304 sp<FakeWindowHandle> window =
13305 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, name,
13306 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013307 window->setOwnerInfo(mPid, mUid);
13308 return window;
13309 }
13310};
13311
13312using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
13313
13314TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013315 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013316 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013317 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013318
13319 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13320 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13321 window->consumeMotionDown();
13322
13323 setFocusedWindow(window);
13324 window->consumeFocusEvent(true);
13325
13326 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13327 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013328 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013329}
13330
13331TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013332 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013333 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013334 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013335
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013336 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013337 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13338 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13339
13340 setFocusedWindow(window);
13341 window->consumeFocusEvent(true);
13342
13343 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13344 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
13345 window->assertNoEvents();
13346}
13347
13348TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013349 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013350 auto window = owner.createWindow("Owned window");
13351 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013352 spy->setSpy(true);
13353 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013354 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013355
13356 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13357 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13358 spy->consumeMotionDown();
13359 window->consumeMotionDown();
13360}
13361
13362TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013363 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013364 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013365
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013366 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013367 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013368 randosSpy->setSpy(true);
13369 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013370 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013371
13372 // The event is targeted at owner's window, so injection should succeed, but the spy should
13373 // not receive the event.
13374 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13375 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13376 randosSpy->assertNoEvents();
13377 window->consumeMotionDown();
13378}
13379
13380TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013381 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013382 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013383
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013384 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013385 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013386 randosSpy->setSpy(true);
13387 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013388 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013389
13390 // A user that has injection permission can inject into any window.
13391 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013392 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013393 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan5735a322022-04-11 17:23:34 +000013394 randosSpy->consumeMotionDown();
13395 window->consumeMotionDown();
13396
13397 setFocusedWindow(randosSpy);
13398 randosSpy->consumeFocusEvent(true);
13399
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013400 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013401 randosSpy->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013402 window->assertNoEvents();
13403}
13404
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013405TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013406 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013407 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013408
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013409 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013410 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013411 randosWindow->setFrame(Rect{-10, -10, -5, -5});
13412 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013413 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013414
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013415 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000013416 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13417 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13418 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013419 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000013420}
13421
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013422using InputDispatcherPointerInWindowTest = InputDispatcherTest;
13423
13424TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
13425 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13426
13427 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013428 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013429 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013430 sp<FakeWindowHandle> right =
13431 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13432 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013433 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013434 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13435 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013436 spy->setFrame(Rect(0, 0, 200, 100));
13437 spy->setTrustedOverlay(true);
13438 spy->setSpy(true);
13439
13440 mDispatcher->onWindowInfosChanged(
13441 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13442
13443 // Hover into the left window.
13444 mDispatcher->notifyMotion(
13445 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
13446 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
13447 .build());
13448
13449 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13450 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13451
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013452 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13453 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013454 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013455 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13456 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013457 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013458 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13459 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013460 /*pointerId=*/0));
13461
13462 // Hover move to the right window.
13463 mDispatcher->notifyMotion(
13464 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
13465 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13466 .build());
13467
13468 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13469 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13470 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
13471
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013472 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13473 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013474 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013475 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13476 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013477 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013478 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13479 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013480 /*pointerId=*/0));
13481
13482 // Stop hovering.
13483 mDispatcher->notifyMotion(
13484 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
13485 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13486 .build());
13487
13488 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13489 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13490
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013491 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13492 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013493 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013494 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13495 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013496 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013497 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13498 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013499 /*pointerId=*/0));
13500}
13501
13502TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
13503 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13504
13505 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013506 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013507 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013508 sp<FakeWindowHandle> right =
13509 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13510 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013511 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013512 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13513 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013514 spy->setFrame(Rect(0, 0, 200, 100));
13515 spy->setTrustedOverlay(true);
13516 spy->setSpy(true);
13517
13518 mDispatcher->onWindowInfosChanged(
13519 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13520
13521 // First pointer down on left window.
13522 mDispatcher->notifyMotion(
13523 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13524 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13525 .build());
13526
13527 left->consumeMotionDown();
13528 spy->consumeMotionDown();
13529
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013530 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13531 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013532 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013533 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13534 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013535 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013536 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13537 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013538 /*pointerId=*/0));
13539
13540 // Second pointer down on right window.
13541 mDispatcher->notifyMotion(
13542 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13543 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13544 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13545 .build());
13546
13547 left->consumeMotionMove();
13548 right->consumeMotionDown();
13549 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
13550
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013551 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13552 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013553 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013554 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13555 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013556 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013557 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13558 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013559 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013560 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13561 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013562 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013563 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13564 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013565 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013566 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13567 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013568 /*pointerId=*/1));
13569
13570 // Second pointer up.
13571 mDispatcher->notifyMotion(
13572 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
13573 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13574 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13575 .build());
13576
13577 left->consumeMotionMove();
13578 right->consumeMotionUp();
13579 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
13580
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013581 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13582 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013583 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013584 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13585 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013586 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013587 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13588 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013589 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013590 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13591 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013592 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013593 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13594 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013595 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013596 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13597 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013598 /*pointerId=*/1));
13599
13600 // First pointer up.
13601 mDispatcher->notifyMotion(
13602 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
13603 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13604 .build());
13605
13606 left->consumeMotionUp();
13607 spy->consumeMotionUp();
13608
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013609 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13610 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013611 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013612 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13613 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013614 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013615 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13616 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013617 /*pointerId=*/0));
13618}
13619
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013620TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse_legacy) {
13621 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013622 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13623
13624 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013625 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013626 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013627 sp<FakeWindowHandle> right =
13628 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13629 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013630 right->setFrame(Rect(100, 0, 200, 100));
13631
13632 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
13633
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013634 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13635 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013636 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013637 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13638 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013639 /*pointerId=*/0));
13640
13641 // Hover move into the window.
13642 mDispatcher->notifyMotion(
13643 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13644 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
13645 .rawXCursorPosition(50)
13646 .rawYCursorPosition(50)
13647 .deviceId(DEVICE_ID)
13648 .build());
13649
13650 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13651
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013652 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13653 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013654 /*pointerId=*/0));
13655
13656 // Move the mouse with another device. This cancels the hovering pointer from the first device.
13657 mDispatcher->notifyMotion(
13658 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13659 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
13660 .rawXCursorPosition(51)
13661 .rawYCursorPosition(50)
13662 .deviceId(SECOND_DEVICE_ID)
13663 .build());
13664
13665 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13666 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13667
13668 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
13669 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013670 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13671 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013672 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013673 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013674 SECOND_DEVICE_ID,
13675 /*pointerId=*/0));
13676
13677 // Move the mouse outside the window. Document the current behavior, where the window does not
13678 // receive HOVER_EXIT even though the mouse left the window.
13679 mDispatcher->notifyMotion(
13680 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13681 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
13682 .rawXCursorPosition(150)
13683 .rawYCursorPosition(50)
13684 .deviceId(SECOND_DEVICE_ID)
13685 .build());
13686
13687 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13688 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013689 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13690 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013691 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013692 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013693 SECOND_DEVICE_ID,
13694 /*pointerId=*/0));
13695}
13696
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013697/**
13698 * TODO(b/313689709) - correctly support multiple mouse devices, because they should be controlling
13699 * the same cursor, and therefore have a shared motion event stream.
13700 */
13701TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
13702 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13703 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13704
13705 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013706 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013707 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013708 sp<FakeWindowHandle> right =
13709 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13710 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013711 right->setFrame(Rect(100, 0, 200, 100));
13712
13713 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
13714
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013715 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13716 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013717 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013718 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13719 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013720 /*pointerId=*/0));
13721
13722 // Hover move into the window.
13723 mDispatcher->notifyMotion(
13724 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13725 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
13726 .rawXCursorPosition(50)
13727 .rawYCursorPosition(50)
13728 .deviceId(DEVICE_ID)
13729 .build());
13730
13731 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13732
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013733 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13734 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013735 /*pointerId=*/0));
13736
13737 // Move the mouse with another device
13738 mDispatcher->notifyMotion(
13739 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13740 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
13741 .rawXCursorPosition(51)
13742 .rawYCursorPosition(50)
13743 .deviceId(SECOND_DEVICE_ID)
13744 .build());
13745 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13746
13747 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
13748 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013749 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13750 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013751 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013752 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013753 SECOND_DEVICE_ID,
13754 /*pointerId=*/0));
13755
13756 // Move the mouse outside the window. Document the current behavior, where the window does not
13757 // receive HOVER_EXIT even though the mouse left the window.
13758 mDispatcher->notifyMotion(
13759 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13760 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
13761 .rawXCursorPosition(150)
13762 .rawYCursorPosition(50)
13763 .deviceId(SECOND_DEVICE_ID)
13764 .build());
13765
13766 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013767 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13768 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013769 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013770 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013771 SECOND_DEVICE_ID,
13772 /*pointerId=*/0));
13773}
13774
Arpit Singhb65e2bd2024-06-03 09:48:16 +000013775TEST_F(InputDispatcherTest, FocusedDisplayChangeIsNotified) {
13776 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
13777 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
13778}
13779
Garfield Tane84e6f92019-08-29 17:28:41 -070013780} // namespace android::inputdispatcher