blob: 48930ef44404d91934e5d26acfcf6838413fb9f3 [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";
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00001285 foregroundWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1286 WithDisplayId(ui::LogicalDisplayId::DEFAULT));
1287 wallpaperWindow->consumeMotionPointerUp(/*pointerIdx=*/0,
1288 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
1289 WithFlags(EXPECTED_WALLPAPER_FLAGS)));
Arthur Hungc539dbb2022-12-08 07:45:36 +00001290
1291 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001292 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001293 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1294 AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001295 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001296 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Harry Cutts101ee9b2023-07-06 18:04:14 +00001297 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER)
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08001298 .x(100)
1299 .y(100))
1300 .build(),
1301 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT))
Arthur Hungc539dbb2022-12-08 07:45:36 +00001302 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001303 foregroundWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
1304 wallpaperWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001305}
1306
1307/**
1308 * Two windows: a window on the left and window on the right.
1309 * A third window, wallpaper, is behind both windows, and spans both top windows.
1310 * The first touch down goes to the left window. A second pointer touches down on the right window.
1311 * The touch is split, so both left and right windows should receive ACTION_DOWN.
1312 * The wallpaper will get the full event, so it should receive ACTION_DOWN followed by
1313 * ACTION_POINTER_DOWN(1).
1314 */
1315TEST_F(InputDispatcherTest, TwoWindows_SplitWallpaperTouch) {
1316 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001317 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1318 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001319 leftWindow->setFrame(Rect(0, 0, 200, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001320 leftWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001321
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001322 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1323 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001324 rightWindow->setFrame(Rect(200, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001325 rightWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001326
1327 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001328 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1329 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001330 wallpaperWindow->setFrame(Rect(0, 0, 400, 200));
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08001331 wallpaperWindow->setIsWallpaper(true);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001332
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001333 mDispatcher->onWindowInfosChanged(
1334 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1335 {},
1336 0,
1337 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001338
1339 // Touch down on left window
1340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001341 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1342 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001343 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1344
1345 // Both foreground window and its wallpaper should receive the touch down
1346 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001347 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001348
1349 // Second finger down on the right window
1350 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001351 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001352 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001353 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1354 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001355 .build();
1356 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001357 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001358 InputEventInjectionSync::WAIT_FOR_RESULT))
1359 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1360
1361 leftWindow->consumeMotionMove();
1362 // Since the touch is split, right window gets ACTION_DOWN
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001363 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1364 wallpaperWindow->consumeMotionPointerDown(/*pointerIndex=*/1, ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08001365 EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001366
1367 // Now, leftWindow, which received the first finger, disappears.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001368 mDispatcher->onWindowInfosChanged(
1369 {{*rightWindow->getInfo(), *wallpaperWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001370 leftWindow->consumeMotionCancel();
1371 // Since a "parent" window of the wallpaper is gone, wallpaper should receive cancel, too.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001372 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001373
1374 // The pointer that's still down on the right window moves, and goes to the right window only.
1375 // As far as the dispatcher's concerned though, both pointers are still present.
1376 const MotionEvent secondFingerMoveEvent =
1377 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
1378 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07001379 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(100))
1380 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(310).y(110))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001381 .build();
1382 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001383 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Siarhei Vishniakouca205502021-07-16 21:31:58 +00001384 InputEventInjectionSync::WAIT_FOR_RESULT));
1385 rightWindow->consumeMotionMove();
1386
1387 leftWindow->assertNoEvents();
1388 rightWindow->assertNoEvents();
1389 wallpaperWindow->assertNoEvents();
1390}
1391
Arthur Hungc539dbb2022-12-08 07:45:36 +00001392/**
1393 * Two windows: a window on the left with dup touch to wallpaper and window on the right without it.
1394 * The touch slips to the right window. so left window and wallpaper should receive ACTION_CANCEL
1395 * The right window should receive ACTION_DOWN.
1396 */
1397TEST_F(InputDispatcherTest, WallpaperWindowWhenSlippery) {
Arthur Hung74c248d2022-11-23 07:09:59 +00001398 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001399 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1400 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001401 leftWindow->setFrame(Rect(0, 0, 200, 200));
1402 leftWindow->setDupTouchToWallpaper(true);
1403 leftWindow->setSlippery(true);
1404
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001405 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1406 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00001407 rightWindow->setFrame(Rect(200, 0, 400, 200));
Arthur Hung74c248d2022-11-23 07:09:59 +00001408
1409 sp<FakeWindowHandle> wallpaperWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001410 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
1411 ui::LogicalDisplayId::DEFAULT);
Arthur Hung74c248d2022-11-23 07:09:59 +00001412 wallpaperWindow->setIsWallpaper(true);
Arthur Hung74c248d2022-11-23 07:09:59 +00001413
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001414 mDispatcher->onWindowInfosChanged(
1415 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *wallpaperWindow->getInfo()},
1416 {},
1417 0,
1418 0});
Arthur Hung74c248d2022-11-23 07:09:59 +00001419
Arthur Hungc539dbb2022-12-08 07:45:36 +00001420 // Touch down on left window
Arthur Hung74c248d2022-11-23 07:09:59 +00001421 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001422 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
1423 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001424 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungc539dbb2022-12-08 07:45:36 +00001425
1426 // Both foreground window and its wallpaper should receive the touch down
1427 leftWindow->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001428 wallpaperWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001429
Arthur Hungc539dbb2022-12-08 07:45:36 +00001430 // Move to right window, the left window should receive cancel.
Arthur Hung74c248d2022-11-23 07:09:59 +00001431 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001432 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001433 ui::LogicalDisplayId::DEFAULT, {201, 100}))
Arthur Hung74c248d2022-11-23 07:09:59 +00001434 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
1435
Arthur Hungc539dbb2022-12-08 07:45:36 +00001436 leftWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001437 rightWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
1438 wallpaperWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hung74c248d2022-11-23 07:09:59 +00001439}
1440
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08001441/**
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001442 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1443 * interactive, it might stop sending this flag.
1444 * In this test, we check that if the policy stops sending this flag mid-gesture, we still ensure
1445 * to have a consistent input stream.
1446 *
1447 * Test procedure:
1448 * DOWN -> POINTER_DOWN -> (stop sending POLICY_FLAG_PASS_TO_USER) -> CANCEL.
1449 * DOWN (new gesture).
1450 *
1451 * In the bad implementation, we could potentially drop the CANCEL event, and get an inconsistent
1452 * state in the dispatcher. This would cause the final DOWN event to not be delivered to the app.
1453 *
1454 * We technically just need a single window here, but we are using two windows (spy on top and a
1455 * regular window below) to emulate the actual situation where it happens on the device.
1456 */
1457TEST_F(InputDispatcherTest, TwoPointerCancelInconsistentPolicy) {
1458 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001459 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
1460 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001461 spyWindow->setFrame(Rect(0, 0, 200, 200));
1462 spyWindow->setTrustedOverlay(true);
1463 spyWindow->setSpy(true);
1464
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001465 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1466 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001467 window->setFrame(Rect(0, 0, 200, 200));
1468
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001469 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001470 const int32_t touchDeviceId = 4;
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001471
1472 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00001473 mDispatcher->notifyMotion(
1474 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1475 .deviceId(touchDeviceId)
1476 .policyFlags(DEFAULT_POLICY_FLAGS)
1477 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1478 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001479
Prabir Pradhan678438e2023-04-13 19:32:51 +00001480 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1481 .deviceId(touchDeviceId)
1482 .policyFlags(DEFAULT_POLICY_FLAGS)
1483 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1484 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1485 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001486 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1487 spyWindow->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1488 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1489 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
1490
1491 // Cancel the current gesture. Send the cancel without the default policy flags.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001492 mDispatcher->notifyMotion(
1493 MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN)
1494 .deviceId(touchDeviceId)
1495 .policyFlags(0)
1496 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1497 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
1498 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001499 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1500 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL));
1501
1502 // We don't need to reset the device to reproduce the issue, but the reset event typically
1503 // follows, so we keep it here to model the actual listener behaviour more closely.
Prabir Pradhan678438e2023-04-13 19:32:51 +00001504 mDispatcher->notifyDeviceReset({/*id=*/1, systemTime(SYSTEM_TIME_MONOTONIC), touchDeviceId});
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001505
1506 // Start new gesture
Prabir Pradhan678438e2023-04-13 19:32:51 +00001507 mDispatcher->notifyMotion(
1508 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1509 .deviceId(touchDeviceId)
1510 .policyFlags(DEFAULT_POLICY_FLAGS)
1511 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1512 .build());
Siarhei Vishniakou5bf25d92023-02-08 15:43:38 -08001513 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1514 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1515
1516 // No more events
1517 spyWindow->assertNoEvents();
1518 window->assertNoEvents();
1519}
1520
1521/**
Linnan Li907ae732023-09-05 17:14:21 +08001522 * Same as the above 'TwoPointerCancelInconsistentPolicy' test, but for hovers.
1523 * The policy typically sets POLICY_FLAG_PASS_TO_USER to the events. But when the display is not
1524 * interactive, it might stop sending this flag.
1525 * We've already ensured the consistency of the touch event in this case, and we should also ensure
1526 * the consistency of the hover event in this case.
1527 *
1528 * Test procedure:
1529 * HOVER_ENTER -> HOVER_MOVE -> (stop sending POLICY_FLAG_PASS_TO_USER) -> HOVER_EXIT
1530 * HOVER_ENTER -> HOVER_MOVE -> HOVER_EXIT
1531 *
1532 * We expect to receive two full streams of hover events.
1533 */
1534TEST_F(InputDispatcherTest, HoverEventInconsistentPolicy) {
1535 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
1536
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001537 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1538 ui::LogicalDisplayId::DEFAULT);
Linnan Li907ae732023-09-05 17:14:21 +08001539 window->setFrame(Rect(0, 0, 300, 300));
1540
1541 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1542
1543 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1544 .policyFlags(DEFAULT_POLICY_FLAGS)
1545 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
1546 .build());
1547 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1548
1549 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1550 .policyFlags(DEFAULT_POLICY_FLAGS)
1551 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1552 .build());
1553 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1554
1555 // Send hover exit without the default policy flags.
1556 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1557 .policyFlags(0)
1558 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
1559 .build());
1560
1561 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1562
1563 // Send a simple hover event stream, ensure dispatcher not crashed and window can receive
1564 // right event.
1565 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1566 .policyFlags(DEFAULT_POLICY_FLAGS)
1567 .pointer(PointerBuilder(0, ToolType::STYLUS).x(200).y(201))
1568 .build());
1569 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1570
1571 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1572 .policyFlags(DEFAULT_POLICY_FLAGS)
1573 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1574 .build());
1575 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1576
1577 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1578 .policyFlags(DEFAULT_POLICY_FLAGS)
1579 .pointer(PointerBuilder(0, ToolType::STYLUS).x(201).y(202))
1580 .build());
1581 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1582}
1583
1584/**
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001585 * Two windows: a window on the left and a window on the right.
1586 * Mouse is hovered from the right window into the left window.
1587 * Next, we tap on the left window, where the cursor was last seen.
1588 * The second tap is done onto the right window.
1589 * The mouse and tap are from two different devices.
1590 * We technically don't need to set the downtime / eventtime for these events, but setting these
1591 * explicitly helps during debugging.
1592 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1593 * In the buggy implementation, a tap on the right window would cause a crash.
1594 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001595TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap_legacy) {
1596 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
1597
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001598 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001599 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1600 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001601 leftWindow->setFrame(Rect(0, 0, 200, 200));
1602
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001603 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1604 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001605 rightWindow->setFrame(Rect(200, 0, 400, 200));
1606
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001607 mDispatcher->onWindowInfosChanged(
1608 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001609 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1610 // stale.
1611 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1612 const int32_t mouseDeviceId = 6;
1613 const int32_t touchDeviceId = 4;
1614 // Move the cursor from right
1615 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001616 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001617 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1618 AINPUT_SOURCE_MOUSE)
1619 .deviceId(mouseDeviceId)
1620 .downTime(baseTime + 10)
1621 .eventTime(baseTime + 20)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001622 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001623 .build()));
1624 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1625
1626 // .. to the left window
1627 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001628 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001629 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
1630 AINPUT_SOURCE_MOUSE)
1631 .deviceId(mouseDeviceId)
1632 .downTime(baseTime + 10)
1633 .eventTime(baseTime + 30)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001634 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001635 .build()));
1636 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1637 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1638 // Now tap the left window
1639 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001640 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001641 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1642 AINPUT_SOURCE_TOUCHSCREEN)
1643 .deviceId(touchDeviceId)
1644 .downTime(baseTime + 40)
1645 .eventTime(baseTime + 40)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001646 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001647 .build()));
1648 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1649 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1650
1651 // release tap
1652 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001653 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001654 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1655 AINPUT_SOURCE_TOUCHSCREEN)
1656 .deviceId(touchDeviceId)
1657 .downTime(baseTime + 40)
1658 .eventTime(baseTime + 50)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001659 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001660 .build()));
1661 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1662
1663 // Tap the window on the right
1664 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001665 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001666 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
1667 AINPUT_SOURCE_TOUCHSCREEN)
1668 .deviceId(touchDeviceId)
1669 .downTime(baseTime + 60)
1670 .eventTime(baseTime + 60)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001671 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001672 .build()));
1673 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1674
1675 // release tap
1676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001677 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001678 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
1679 AINPUT_SOURCE_TOUCHSCREEN)
1680 .deviceId(touchDeviceId)
1681 .downTime(baseTime + 60)
1682 .eventTime(baseTime + 70)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07001683 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakoue0431e42023-01-28 17:01:39 -08001684 .build()));
1685 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1686
1687 // No more events
1688 leftWindow->assertNoEvents();
1689 rightWindow->assertNoEvents();
1690}
1691
1692/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001693 * Two windows: a window on the left and a window on the right.
1694 * Mouse is hovered from the right window into the left window.
1695 * Next, we tap on the left window, where the cursor was last seen.
1696 * The second tap is done onto the right window.
1697 * The mouse and tap are from two different devices.
1698 * We technically don't need to set the downtime / eventtime for these events, but setting these
1699 * explicitly helps during debugging.
1700 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
1701 * In the buggy implementation, a tap on the right window would cause a crash.
1702 */
1703TEST_F(InputDispatcherTest, HoverFromLeftToRightAndTap) {
1704 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
1705
1706 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001707 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
1708 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001709 leftWindow->setFrame(Rect(0, 0, 200, 200));
1710
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001711 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
1712 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07001713 rightWindow->setFrame(Rect(200, 0, 400, 200));
1714
1715 mDispatcher->onWindowInfosChanged(
1716 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
1717 // All times need to start at the current time, otherwise the dispatcher will drop the events as
1718 // stale.
1719 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
1720 const int32_t mouseDeviceId = 6;
1721 const int32_t touchDeviceId = 4;
1722 // Move the cursor from right
1723 mDispatcher->notifyMotion(
1724 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1725 .deviceId(mouseDeviceId)
1726 .downTime(baseTime + 10)
1727 .eventTime(baseTime + 20)
1728 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(100))
1729 .build());
1730 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1731
1732 // .. to the left window
1733 mDispatcher->notifyMotion(
1734 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1735 .deviceId(mouseDeviceId)
1736 .downTime(baseTime + 10)
1737 .eventTime(baseTime + 30)
1738 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(100))
1739 .build());
1740 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
1741 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
1742 // Now tap the left window
1743 mDispatcher->notifyMotion(
1744 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1745 .deviceId(touchDeviceId)
1746 .downTime(baseTime + 40)
1747 .eventTime(baseTime + 40)
1748 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1749 .build());
1750 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1751
1752 // release tap
1753 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1754 .deviceId(touchDeviceId)
1755 .downTime(baseTime + 40)
1756 .eventTime(baseTime + 50)
1757 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
1758 .build());
1759 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1760
1761 // Tap the window on the right
1762 mDispatcher->notifyMotion(
1763 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
1764 .deviceId(touchDeviceId)
1765 .downTime(baseTime + 60)
1766 .eventTime(baseTime + 60)
1767 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1768 .build());
1769 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
1770
1771 // release tap
1772 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
1773 .deviceId(touchDeviceId)
1774 .downTime(baseTime + 60)
1775 .eventTime(baseTime + 70)
1776 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
1777 .build());
1778 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
1779
1780 // No more events
1781 leftWindow->assertNoEvents();
1782 rightWindow->assertNoEvents();
1783}
1784
1785/**
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001786 * Start hovering in a window. While this hover is still active, make another window appear on top.
1787 * The top, obstructing window has no input channel, so it's not supposed to receive input.
1788 * While the top window is present, the hovering is stopped.
1789 * Later, hovering gets resumed again.
1790 * Ensure that new hover gesture is handled correctly.
1791 * This test reproduces a crash where the HOVER_EXIT event wasn't getting dispatched correctly
1792 * to the window that's currently being hovered over.
1793 */
1794TEST_F(InputDispatcherTest, HoverWhileWindowAppears) {
1795 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001796 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1797 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001798 window->setFrame(Rect(0, 0, 200, 200));
1799
1800 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001801 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001802
1803 // Start hovering in the window
1804 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1805 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1806 .build());
1807 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1808
1809 // Now, an obscuring window appears!
1810 sp<FakeWindowHandle> obscuringWindow =
1811 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001812 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001813 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001814 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1815 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1816 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1817 obscuringWindow->setNoInputChannel(true);
1818 obscuringWindow->setFocusable(false);
1819 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001820 mDispatcher->onWindowInfosChanged(
1821 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001822
1823 // While this new obscuring window is present, the hovering is stopped
1824 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
1825 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1826 .build());
1827 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1828
1829 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001830 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001831
1832 // And a new hover gesture starts.
1833 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1834 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1835 .build());
1836 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1837}
1838
1839/**
1840 * Same test as 'HoverWhileWindowAppears' above, but here, we also send some HOVER_MOVE events to
1841 * the obscuring window.
1842 */
1843TEST_F(InputDispatcherTest, HoverMoveWhileWindowAppears) {
1844 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001845 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1846 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001847 window->setFrame(Rect(0, 0, 200, 200));
1848
1849 // Only a single window is present at first
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001850 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001851
1852 // Start hovering in the window
1853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
1854 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1855 .build());
1856 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1857
1858 // Now, an obscuring window appears!
1859 sp<FakeWindowHandle> obscuringWindow =
1860 sp<FakeWindowHandle>::make(application, mDispatcher, "Obscuring window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001861 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhane7cc69c2024-01-05 21:35:28 +00001862 /*createInputChannel=*/false);
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001863 obscuringWindow->setFrame(Rect(0, 0, 200, 200));
1864 obscuringWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
1865 obscuringWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
1866 obscuringWindow->setNoInputChannel(true);
1867 obscuringWindow->setFocusable(false);
1868 obscuringWindow->setAlpha(1.0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001869 mDispatcher->onWindowInfosChanged(
1870 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001871
1872 // While this new obscuring window is present, the hovering continues. The event can't go to the
1873 // bottom window due to obstructed touches, so it should generate HOVER_EXIT for that window.
1874 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1875 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1876 .build());
1877 obscuringWindow->assertNoEvents();
1878 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1879
1880 // Now the obscuring window goes away.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07001881 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07001882
1883 // Hovering continues in the same position. The hovering pointer re-enters the bottom window,
1884 // so it should generate a HOVER_ENTER
1885 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1886 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
1887 .build());
1888 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1889
1890 // Now the MOVE should be getting dispatched normally
1891 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
1892 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
1893 .build());
1894 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1895}
1896
1897/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001898 * Hover mouse over a window, and then send ACTION_SCROLL. Ensure both the hover and the scroll
1899 * events are delivered to the window.
1900 */
1901TEST_F(InputDispatcherTest, HoverMoveAndScroll) {
1902 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07001903 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
1904 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07001905 window->setFrame(Rect(0, 0, 200, 200));
1906 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
1907
1908 // Start hovering in the window
1909 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
1910 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1911 .build());
1912 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1913
1914 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1915 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1916 .build());
1917 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
1918
1919 // Scroll with the mouse
1920 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_SCROLL, AINPUT_SOURCE_MOUSE)
1921 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
1922 .build());
1923 window->consumeMotionEvent(WithMotionAction(ACTION_SCROLL));
1924}
1925
Siarhei Vishniakoua8aaeb82024-08-12 12:00:28 -07001926/**
1927 * Two windows: a trusted overlay and a regular window underneath. Both windows are visible.
1928 * Mouse is hovered, and the hover event should only go to the overlay.
1929 * However, next, the touchable region of the trusted overlay shrinks. The mouse position hasn't
1930 * changed, but the cursor would now end up hovering above the regular window underneatch.
1931 * If the mouse is now clicked, this would generate an ACTION_DOWN event, which would go to the
1932 * regular window. However, the trusted overlay is also watching for outside touch.
1933 * The trusted overlay should get two events:
1934 * 1) The ACTION_OUTSIDE event, since the click is now not inside its touchable region
1935 * 2) The HOVER_EXIT event, since the mouse pointer is no longer hovering inside this window
1936 *
1937 * This test reproduces a crash where there is an overlap between dispatch modes for the trusted
1938 * overlay touch target, since the event is causing both an ACTION_OUTSIDE, and as a HOVER_EXIT.
1939 */
1940TEST_F(InputDispatcherTest, MouseClickUnderShrinkingTrustedOverlay) {
1941 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
1942 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(app, mDispatcher, "Trusted overlay",
1943 ui::LogicalDisplayId::DEFAULT);
1944 overlay->setTrustedOverlay(true);
1945 overlay->setWatchOutsideTouch(true);
1946 overlay->setFrame(Rect(0, 0, 200, 200));
1947
1948 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(app, mDispatcher, "Regular window",
1949 ui::LogicalDisplayId::DEFAULT);
1950 window->setFrame(Rect(0, 0, 200, 200));
1951
1952 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1953 // Hover the mouse into the overlay
1954 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1955 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1956 .build());
1957 overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
1958
1959 // Now, shrink the touchable region of the overlay! This will cause the cursor to suddenly have
1960 // the regular window as the touch target
1961 overlay->setTouchableRegion(Region({0, 0, 0, 0}));
1962 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1963
1964 // Now we can click with the mouse. The click should go into the regular window
1965 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
1966 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
1967 .build());
1968 overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
1969 overlay->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
1970 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
1971}
1972
1973/**
1974 * Similar to above, but also has a spy on top that also catches the HOVER
1975 * events. Also, instead of ACTION_DOWN, we are continuing to send the hovering
1976 * stream to ensure that the spy receives hover events correctly.
1977 */
1978TEST_F(InputDispatcherTest, MouseClickUnderShrinkingTrustedOverlayWithSpy) {
1979 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
1980 sp<FakeWindowHandle> spyWindow =
1981 sp<FakeWindowHandle>::make(app, mDispatcher, "Spy", ui::LogicalDisplayId::DEFAULT);
1982 spyWindow->setFrame(Rect(0, 0, 200, 200));
1983 spyWindow->setTrustedOverlay(true);
1984 spyWindow->setSpy(true);
1985 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(app, mDispatcher, "Trusted overlay",
1986 ui::LogicalDisplayId::DEFAULT);
1987 overlay->setTrustedOverlay(true);
1988 overlay->setWatchOutsideTouch(true);
1989 overlay->setFrame(Rect(0, 0, 200, 200));
1990
1991 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(app, mDispatcher, "Regular window",
1992 ui::LogicalDisplayId::DEFAULT);
1993 window->setFrame(Rect(0, 0, 200, 200));
1994
1995 mDispatcher->onWindowInfosChanged(
1996 {{*spyWindow->getInfo(), *overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
1997 // Hover the mouse into the overlay
1998 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
1999 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2000 .build());
2001 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2002 overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2003
2004 // Now, shrink the touchable region of the overlay! This will cause the cursor to suddenly have
2005 // the regular window as the touch target
2006 overlay->setTouchableRegion(Region({0, 0, 0, 0}));
2007 mDispatcher->onWindowInfosChanged(
2008 {{*spyWindow->getInfo(), *overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
2009
2010 // Now we can click with the mouse. The click should go into the regular window
2011 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2012 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
2013 .build());
2014 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
2015 overlay->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
2016 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
2017}
2018
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002019using InputDispatcherMultiDeviceTest = InputDispatcherTest;
2020
2021/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002022 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2023 * touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002024 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002025TEST_F(InputDispatcherMultiDeviceTest, StylusDownBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002026 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002027 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002028 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2029 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002030 window->setFrame(Rect(0, 0, 200, 200));
2031
2032 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2033
2034 constexpr int32_t touchDeviceId = 4;
2035 constexpr int32_t stylusDeviceId = 2;
2036
2037 // Stylus down
2038 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2039 .deviceId(stylusDeviceId)
2040 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2041 .build());
2042 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2043
2044 // Touch down
2045 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2046 .deviceId(touchDeviceId)
2047 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2048 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002049
2050 // Touch move
2051 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2052 .deviceId(touchDeviceId)
2053 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2054 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002055 // Touch is ignored because stylus is already down
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002056
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002057 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002058 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2059 .deviceId(stylusDeviceId)
2060 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2061 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002062 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2063 WithCoords(101, 111)));
2064
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002065 window->assertNoEvents();
2066}
2067
2068/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002069 * One window. Stylus down on the window. Next, touch from another device goes down. Ensure that
2070 * touch is not dropped, because multiple devices are allowed to be active in the same window.
2071 */
2072TEST_F(InputDispatcherMultiDeviceTest, StylusDownDoesNotBlockTouchDown) {
2073 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2074 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002075 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2076 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002077 window->setFrame(Rect(0, 0, 200, 200));
2078
2079 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2080
2081 constexpr int32_t touchDeviceId = 4;
2082 constexpr int32_t stylusDeviceId = 2;
2083
2084 // Stylus down
2085 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2086 .deviceId(stylusDeviceId)
2087 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2088 .build());
2089 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2090
2091 // Touch down
2092 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2093 .deviceId(touchDeviceId)
2094 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2095 .build());
2096 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2097
2098 // Touch move
2099 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2100 .deviceId(touchDeviceId)
2101 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2102 .build());
2103 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2104
2105 // Stylus move
2106 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2107 .deviceId(stylusDeviceId)
2108 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2109 .build());
2110 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2111 WithCoords(101, 111)));
2112
2113 window->assertNoEvents();
2114}
2115
2116/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002117 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002118 * down. Ensure that touch is dropped, because stylus should be preferred over touch.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002119 * Similar test as above, but with added SPY window.
2120 */
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002121TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002122 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002123 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002124 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2125 ui::LogicalDisplayId::DEFAULT);
2126 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2127 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002128 spyWindow->setFrame(Rect(0, 0, 200, 200));
2129 spyWindow->setTrustedOverlay(true);
2130 spyWindow->setSpy(true);
2131 window->setFrame(Rect(0, 0, 200, 200));
2132
2133 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2134
2135 constexpr int32_t touchDeviceId = 4;
2136 constexpr int32_t stylusDeviceId = 2;
2137
2138 // Stylus down
2139 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2140 .deviceId(stylusDeviceId)
2141 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2142 .build());
2143 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2144 spyWindow->consumeMotionEvent(
2145 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2146
2147 // Touch down
2148 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2149 .deviceId(touchDeviceId)
2150 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2151 .build());
2152
2153 // Touch move
2154 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2155 .deviceId(touchDeviceId)
2156 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2157 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002158
2159 // Touch is ignored because stylus is already down
2160
2161 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002162 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2163 .deviceId(stylusDeviceId)
2164 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2165 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002166 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2167 WithCoords(101, 111)));
2168 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2169 WithCoords(101, 111)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002170
2171 window->assertNoEvents();
2172 spyWindow->assertNoEvents();
2173}
2174
2175/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002176 * One window and one spy window. Stylus down on the window. Next, touch from another device goes
2177 * down. Ensure that touch is not dropped, because multiple devices can be active at the same time.
2178 * Similar test as above, but with added SPY window.
2179 */
2180TEST_F(InputDispatcherMultiDeviceTest, StylusDownWithSpyDoesNotBlockTouchDown) {
2181 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2182 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002183 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2184 ui::LogicalDisplayId::DEFAULT);
2185 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2186 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002187 spyWindow->setFrame(Rect(0, 0, 200, 200));
2188 spyWindow->setTrustedOverlay(true);
2189 spyWindow->setSpy(true);
2190 window->setFrame(Rect(0, 0, 200, 200));
2191
2192 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
2193
2194 constexpr int32_t touchDeviceId = 4;
2195 constexpr int32_t stylusDeviceId = 2;
2196
2197 // Stylus down
2198 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2199 .deviceId(stylusDeviceId)
2200 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2201 .build());
2202 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2203 spyWindow->consumeMotionEvent(
2204 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2205
2206 // Touch down
2207 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2208 .deviceId(touchDeviceId)
2209 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2210 .build());
2211 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2212 spyWindow->consumeMotionEvent(
2213 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2214
2215 // Touch move
2216 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2217 .deviceId(touchDeviceId)
2218 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2219 .build());
2220 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2221 spyWindow->consumeMotionEvent(
2222 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2223
2224 // Subsequent stylus movements are delivered correctly
2225 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2226 .deviceId(stylusDeviceId)
2227 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2228 .build());
2229 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2230 WithCoords(101, 111)));
2231 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2232 WithCoords(101, 111)));
2233
2234 window->assertNoEvents();
2235 spyWindow->assertNoEvents();
2236}
2237
2238/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002239 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002240 * touch is dropped, because stylus hover takes precedence.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002241 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002242TEST_F(InputDispatcherMultiDeviceTest, StylusHoverBlocksTouchDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002243 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002244 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002245 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2246 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002247 window->setFrame(Rect(0, 0, 200, 200));
2248
2249 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2250
2251 constexpr int32_t touchDeviceId = 4;
2252 constexpr int32_t stylusDeviceId = 2;
2253
2254 // Stylus down on the window
2255 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2256 .deviceId(stylusDeviceId)
2257 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2258 .build());
2259 window->consumeMotionEvent(
2260 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2261
2262 // Touch down on window
2263 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2264 .deviceId(touchDeviceId)
2265 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2266 .build());
2267 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2268 .deviceId(touchDeviceId)
2269 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2270 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002271
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002272 // Touch is ignored because stylus is hovering
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002273
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002274 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002275 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2276 .deviceId(stylusDeviceId)
2277 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2278 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002279 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2280 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002281
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002282 // and subsequent touches continue to be ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002283 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2284 .deviceId(touchDeviceId)
2285 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2286 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002287 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002288}
2289
2290/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002291 * One window. Stylus hover on the window. Next, touch from another device goes down. Ensure that
2292 * touch is not dropped, because stylus hover and touch can be both active at the same time.
2293 */
2294TEST_F(InputDispatcherMultiDeviceTest, StylusHoverDoesNotBlockTouchDown) {
2295 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2296 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002297 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2298 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002299 window->setFrame(Rect(0, 0, 200, 200));
2300
2301 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2302
2303 constexpr int32_t touchDeviceId = 4;
2304 constexpr int32_t stylusDeviceId = 2;
2305
2306 // Stylus down on the window
2307 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2308 .deviceId(stylusDeviceId)
2309 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2310 .build());
2311 window->consumeMotionEvent(
2312 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2313
2314 // Touch down on window
2315 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2316 .deviceId(touchDeviceId)
2317 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2318 .build());
2319 // Touch move on window
2320 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2321 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2322 .deviceId(touchDeviceId)
2323 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2324 .build());
2325 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2326
2327 // Subsequent stylus movements are delivered correctly
2328 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2329 .deviceId(stylusDeviceId)
2330 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2331 .build());
2332 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2333 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2334
2335 // and subsequent touches continue to work
2336 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2337 .deviceId(touchDeviceId)
2338 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2339 .build());
2340 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2341 window->assertNoEvents();
2342}
2343
2344/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002345 * One window. Touch down on the window. Then, stylus hover on the window from another device.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002346 * Ensure that touch is canceled, because stylus hover should take precedence.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002347 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002348TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusHover) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002349 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002350 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002351 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2352 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002353 window->setFrame(Rect(0, 0, 200, 200));
2354
2355 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2356
2357 constexpr int32_t touchDeviceId = 4;
2358 constexpr int32_t stylusDeviceId = 2;
2359
2360 // Touch down on window
2361 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2362 .deviceId(touchDeviceId)
2363 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2364 .build());
2365 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2366 .deviceId(touchDeviceId)
2367 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2368 .build());
2369 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2370 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2371
2372 // Stylus hover on the window
2373 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2374 .deviceId(stylusDeviceId)
2375 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2376 .build());
2377 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2378 .deviceId(stylusDeviceId)
2379 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2380 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002381 // Stylus hover movement causes touch to be canceled
2382 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
2383 WithCoords(141, 146)));
2384 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2385 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2386 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2387 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002388
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002389 // Subsequent touch movements are ignored
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002390 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2391 .deviceId(touchDeviceId)
2392 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2393 .build());
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07002394
2395 window->assertNoEvents();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002396}
2397
2398/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002399 * One window. Touch down on the window. Then, stylus hover on the window from another device.
2400 * Ensure that touch is not canceled, because stylus hover can be active at the same time as touch.
2401 */
2402TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusHover) {
2403 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2404 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002405 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2406 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002407 window->setFrame(Rect(0, 0, 200, 200));
2408
2409 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2410
2411 constexpr int32_t touchDeviceId = 4;
2412 constexpr int32_t stylusDeviceId = 2;
2413
2414 // Touch down on window
2415 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2416 .deviceId(touchDeviceId)
2417 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2418 .build());
2419 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2420 .deviceId(touchDeviceId)
2421 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2422 .build());
2423 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2424 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2425
2426 // Stylus hover on the window
2427 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2428 .deviceId(stylusDeviceId)
2429 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2430 .build());
2431 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2432 .deviceId(stylusDeviceId)
2433 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2434 .build());
2435 // Stylus hover movement is received normally
2436 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
2437 WithDeviceId(stylusDeviceId), WithCoords(100, 110)));
2438 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE),
2439 WithDeviceId(stylusDeviceId), WithCoords(101, 111)));
2440
2441 // Subsequent touch movements also work
2442 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2443 .deviceId(touchDeviceId)
2444 .pointer(PointerBuilder(0, ToolType::FINGER).x(142).y(147))
2445 .build());
2446 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId),
2447 WithCoords(142, 147)));
2448
2449 window->assertNoEvents();
2450}
2451
2452/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002453 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2454 * the latest stylus takes over. That is, old stylus should be canceled and the new stylus should
2455 * become active.
2456 */
2457TEST_F(InputDispatcherMultiDeviceTest, LatestStylusWins) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002458 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002459 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002460 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2461 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002462 window->setFrame(Rect(0, 0, 200, 200));
2463
2464 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2465
2466 constexpr int32_t stylusDeviceId1 = 3;
2467 constexpr int32_t stylusDeviceId2 = 5;
2468
2469 // Touch down on window
2470 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2471 .deviceId(stylusDeviceId1)
2472 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2473 .build());
2474 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2475 .deviceId(stylusDeviceId1)
2476 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2477 .build());
2478 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2479 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2480
2481 // Second stylus down
2482 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2483 .deviceId(stylusDeviceId2)
2484 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2485 .build());
2486 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2487 .deviceId(stylusDeviceId2)
2488 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2489 .build());
2490
2491 // First stylus is canceled, second one takes over.
2492 window->consumeMotionEvent(
2493 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId1)));
2494 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2495 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2496
2497 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2498 .deviceId(stylusDeviceId1)
2499 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2500 .build());
2501 // Subsequent stylus movements are delivered correctly
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002502 window->assertNoEvents();
2503}
2504
2505/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002506 * One window. Stylus down on the window. Then, stylus from another device goes down. Ensure that
2507 * both stylus devices can function simultaneously.
2508 */
2509TEST_F(InputDispatcherMultiDeviceTest, TwoStylusDevicesActiveAtTheSameTime) {
2510 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2511 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002512 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2513 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002514 window->setFrame(Rect(0, 0, 200, 200));
2515
2516 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2517
2518 constexpr int32_t stylusDeviceId1 = 3;
2519 constexpr int32_t stylusDeviceId2 = 5;
2520
2521 // Touch down on window
2522 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2523 .deviceId(stylusDeviceId1)
2524 .pointer(PointerBuilder(0, ToolType::STYLUS).x(99).y(100))
2525 .build());
2526 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2527 .deviceId(stylusDeviceId1)
2528 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(101))
2529 .build());
2530 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId1)));
2531 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2532
2533 // Second stylus down
2534 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2535 .deviceId(stylusDeviceId2)
2536 .pointer(PointerBuilder(0, ToolType::STYLUS).x(9).y(10))
2537 .build());
2538 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2539 .deviceId(stylusDeviceId2)
2540 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(11))
2541 .build());
2542 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId2)));
2543 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId2)));
2544
2545 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2546 .deviceId(stylusDeviceId1)
2547 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(102))
2548 .build());
2549 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId1)));
2550 window->assertNoEvents();
2551}
2552
2553/**
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002554 * One window. Touch down on the window. Then, stylus down on the window from another device.
2555 * Ensure that is canceled, because stylus down should be preferred over touch.
2556 */
2557TEST_F(InputDispatcherMultiDeviceTest, TouchIsCanceledByStylusDown) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002558 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002559 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002560 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2561 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002562 window->setFrame(Rect(0, 0, 200, 200));
2563
2564 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2565
2566 constexpr int32_t touchDeviceId = 4;
2567 constexpr int32_t stylusDeviceId = 2;
2568
2569 // Touch down on window
2570 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2571 .deviceId(touchDeviceId)
2572 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2573 .build());
2574 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2575 .deviceId(touchDeviceId)
2576 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2577 .build());
2578 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2579 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2580
2581 // Stylus down on the window
2582 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2583 .deviceId(stylusDeviceId)
2584 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2585 .build());
2586 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
2587 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2588
2589 // Subsequent stylus movements are delivered correctly
2590 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2591 .deviceId(stylusDeviceId)
2592 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2593 .build());
2594 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2595 WithCoords(101, 111)));
2596}
2597
2598/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002599 * One window. Touch down on the window. Then, stylus down on the window from another device.
2600 * Ensure that both touch and stylus are functioning independently.
2601 */
2602TEST_F(InputDispatcherMultiDeviceTest, TouchIsNotCanceledByStylusDown) {
2603 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2604 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002605 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
2606 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002607 window->setFrame(Rect(0, 0, 200, 200));
2608
2609 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
2610
2611 constexpr int32_t touchDeviceId = 4;
2612 constexpr int32_t stylusDeviceId = 2;
2613
2614 // Touch down on window
2615 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2616 .deviceId(touchDeviceId)
2617 .pointer(PointerBuilder(0, ToolType::FINGER).x(140).y(145))
2618 .build());
2619 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2620 .deviceId(touchDeviceId)
2621 .pointer(PointerBuilder(0, ToolType::FINGER).x(141).y(146))
2622 .build());
2623 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2624 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2625
2626 // Stylus down on the window
2627 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2628 .deviceId(stylusDeviceId)
2629 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(110))
2630 .build());
2631 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2632
2633 // Subsequent stylus movements are delivered correctly
2634 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2635 .deviceId(stylusDeviceId)
2636 .pointer(PointerBuilder(0, ToolType::STYLUS).x(101).y(111))
2637 .build());
2638 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId),
2639 WithCoords(101, 111)));
2640
2641 // Touch continues to work too
2642 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2643 .deviceId(touchDeviceId)
2644 .pointer(PointerBuilder(0, ToolType::FINGER).x(148).y(149))
2645 .build());
2646 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
2647}
2648
2649/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002650 * Two windows: a window on the left and a window on the right.
2651 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2652 * down. Then, on the left window, also place second touch pointer down.
2653 * This test tries to reproduce a crash.
2654 * In the buggy implementation, second pointer down on the left window would cause a crash.
2655 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002656TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch_legacy) {
2657 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002658 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002659 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2660 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002661 leftWindow->setFrame(Rect(0, 0, 200, 200));
2662
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002663 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2664 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002665 rightWindow->setFrame(Rect(200, 0, 400, 200));
2666
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07002667 mDispatcher->onWindowInfosChanged(
2668 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002669
2670 const int32_t touchDeviceId = 4;
2671 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002672
2673 // Start hovering over the left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002674 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2675 .deviceId(mouseDeviceId)
2676 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2677 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002678 leftWindow->consumeMotionEvent(
2679 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2680
2681 // Mouse down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002682 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2683 .deviceId(mouseDeviceId)
2684 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2685 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2686 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002687
2688 leftWindow->consumeMotionEvent(
2689 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2690 leftWindow->consumeMotionEvent(
2691 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2692
Prabir Pradhan678438e2023-04-13 19:32:51 +00002693 mDispatcher->notifyMotion(
2694 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2695 .deviceId(mouseDeviceId)
2696 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2697 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2698 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2699 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002700 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2701
2702 // First touch pointer down on right window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002703 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2704 .deviceId(touchDeviceId)
2705 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2706 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002707 leftWindow->assertNoEvents();
2708
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002709 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2710
2711 // Second touch pointer down on left window
Prabir Pradhan678438e2023-04-13 19:32:51 +00002712 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2713 .deviceId(touchDeviceId)
2714 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2715 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2716 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002717 // Since this is now a new splittable pointer going down on the left window, and it's coming
2718 // from a different device, the current gesture in the left window (pointer down) should first
2719 // be canceled.
2720 leftWindow->consumeMotionEvent(
2721 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08002722 leftWindow->consumeMotionEvent(
2723 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2724 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2725 // current implementation.
2726 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2727 rightWindow->consumeMotionEvent(
2728 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2729
2730 leftWindow->assertNoEvents();
2731 rightWindow->assertNoEvents();
2732}
2733
2734/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002735 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002736 * Mouse is clicked on the left window and remains down. Touch is touched on the right and remains
2737 * down. Then, on the left window, also place second touch pointer down.
2738 * This test tries to reproduce a crash.
2739 * In the buggy implementation, second pointer down on the left window would cause a crash.
2740 */
2741TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceSplitTouch) {
2742 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2743 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002744 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2745 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002746 leftWindow->setFrame(Rect(0, 0, 200, 200));
2747
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002748 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2749 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002750 rightWindow->setFrame(Rect(200, 0, 400, 200));
2751
2752 mDispatcher->onWindowInfosChanged(
2753 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2754
2755 const int32_t touchDeviceId = 4;
2756 const int32_t mouseDeviceId = 6;
2757
2758 // Start hovering over the left window
2759 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2760 .deviceId(mouseDeviceId)
2761 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2762 .build());
2763 leftWindow->consumeMotionEvent(
2764 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2765
2766 // Mouse down on left window
2767 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
2768 .deviceId(mouseDeviceId)
2769 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2770 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2771 .build());
2772
2773 leftWindow->consumeMotionEvent(
2774 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
2775 leftWindow->consumeMotionEvent(
2776 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
2777
2778 mDispatcher->notifyMotion(
2779 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
2780 .deviceId(mouseDeviceId)
2781 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
2782 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
2783 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
2784 .build());
2785 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
2786
2787 // First touch pointer down on right window
2788 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2789 .deviceId(touchDeviceId)
2790 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2791 .build());
2792 leftWindow->assertNoEvents();
2793
2794 rightWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
2795
2796 // Second touch pointer down on left window
2797 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2798 .deviceId(touchDeviceId)
2799 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2800 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
2801 .build());
2802 // Since this is now a new splittable pointer going down on the left window, and it's coming
2803 // from a different device, it will be split and delivered to left window separately.
2804 leftWindow->consumeMotionEvent(
2805 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2806 // This MOVE event is not necessary (doesn't carry any new information), but it's there in the
2807 // current implementation.
2808 const std::map<int32_t, PointF> expectedPointers{{0, PointF{100, 100}}};
2809 rightWindow->consumeMotionEvent(
2810 AllOf(WithMotionAction(ACTION_MOVE), WithPointers(expectedPointers)));
2811
2812 leftWindow->assertNoEvents();
2813 rightWindow->assertNoEvents();
2814}
2815
2816/**
2817 * Two windows: a window on the left and a window on the right.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002818 * Mouse is hovered on the left window and stylus is hovered on the right window.
2819 */
2820TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHover) {
2821 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002822 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2823 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002824 leftWindow->setFrame(Rect(0, 0, 200, 200));
2825
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002826 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2827 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002828 rightWindow->setFrame(Rect(200, 0, 400, 200));
2829
2830 mDispatcher->onWindowInfosChanged(
2831 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2832
2833 const int32_t stylusDeviceId = 3;
2834 const int32_t mouseDeviceId = 6;
2835
2836 // Start hovering over the left window
2837 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
2838 .deviceId(mouseDeviceId)
2839 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
2840 .build());
2841 leftWindow->consumeMotionEvent(
2842 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
2843
2844 // Stylus hovered on right window
2845 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
2846 .deviceId(stylusDeviceId)
2847 .pointer(PointerBuilder(0, ToolType::STYLUS).x(300).y(100))
2848 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002849 rightWindow->consumeMotionEvent(
2850 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
2851
2852 // Subsequent HOVER_MOVE events are dispatched correctly.
2853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
2854 .deviceId(mouseDeviceId)
2855 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(120))
2856 .build());
2857 leftWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002858 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(mouseDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002859
2860 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
2861 .deviceId(stylusDeviceId)
2862 .pointer(PointerBuilder(0, ToolType::STYLUS).x(310).y(110))
2863 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002864 rightWindow->consumeMotionEvent(
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002865 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002866
2867 leftWindow->assertNoEvents();
2868 rightWindow->assertNoEvents();
2869}
2870
2871/**
2872 * Three windows: a window on the left and a window on the right.
2873 * And a spy window that's positioned above all of them.
2874 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2875 * Check the stream that's received by the spy.
2876 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002877TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy_legacy) {
2878 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002879 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2880
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002881 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2882 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002883 spyWindow->setFrame(Rect(0, 0, 400, 400));
2884 spyWindow->setTrustedOverlay(true);
2885 spyWindow->setSpy(true);
2886
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002887 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2888 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002889 leftWindow->setFrame(Rect(0, 0, 200, 200));
2890
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002891 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2892 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002893
2894 rightWindow->setFrame(Rect(200, 0, 400, 200));
2895
2896 mDispatcher->onWindowInfosChanged(
2897 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2898
2899 const int32_t stylusDeviceId = 1;
2900 const int32_t touchDeviceId = 2;
2901
2902 // Stylus down on the left window
2903 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2904 .deviceId(stylusDeviceId)
2905 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2906 .build());
2907 leftWindow->consumeMotionEvent(
2908 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2909 spyWindow->consumeMotionEvent(
2910 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2911
2912 // Touch down on the right window
2913 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2914 .deviceId(touchDeviceId)
2915 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2916 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002917 leftWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002918 rightWindow->consumeMotionEvent(
2919 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002920
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002921 // Spy window does not receive touch events, because stylus events take precedence, and it
2922 // already has an active stylus gesture.
2923
2924 // Stylus movements continue. They should be delivered to the left window and to the spy window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002925 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
2926 .deviceId(stylusDeviceId)
2927 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
2928 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002929 leftWindow->consumeMotionEvent(
2930 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
2931 spyWindow->consumeMotionEvent(
2932 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002933
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07002934 // Further MOVE events keep going to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002935 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
2936 .deviceId(touchDeviceId)
2937 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
2938 .build());
2939 rightWindow->consumeMotionEvent(
2940 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07002941
2942 spyWindow->assertNoEvents();
2943 leftWindow->assertNoEvents();
2944 rightWindow->assertNoEvents();
2945}
2946
2947/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002948 * Three windows: a window on the left and a window on the right.
2949 * And a spy window that's positioned above all of them.
2950 * Stylus down on the left window and remains down. Touch goes down on the right and remains down.
2951 * Check the stream that's received by the spy.
2952 */
2953TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceWithSpy) {
2954 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
2955 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
2956
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002957 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
2958 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002959 spyWindow->setFrame(Rect(0, 0, 400, 400));
2960 spyWindow->setTrustedOverlay(true);
2961 spyWindow->setSpy(true);
2962
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002963 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
2964 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002965 leftWindow->setFrame(Rect(0, 0, 200, 200));
2966
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07002967 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
2968 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07002969
2970 rightWindow->setFrame(Rect(200, 0, 400, 200));
2971
2972 mDispatcher->onWindowInfosChanged(
2973 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
2974
2975 const int32_t stylusDeviceId = 1;
2976 const int32_t touchDeviceId = 2;
2977
2978 // Stylus down on the left window
2979 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
2980 .deviceId(stylusDeviceId)
2981 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
2982 .build());
2983 leftWindow->consumeMotionEvent(
2984 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2985 spyWindow->consumeMotionEvent(
2986 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
2987
2988 // Touch down on the right window
2989 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
2990 .deviceId(touchDeviceId)
2991 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
2992 .build());
2993 leftWindow->assertNoEvents();
2994 rightWindow->consumeMotionEvent(
2995 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2996 spyWindow->consumeMotionEvent(
2997 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
2998
2999 // Stylus movements continue. They should be delivered to the left window and to the spy window
3000 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3001 .deviceId(stylusDeviceId)
3002 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3003 .build());
3004 leftWindow->consumeMotionEvent(
3005 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3006 spyWindow->consumeMotionEvent(
3007 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3008
3009 // Further touch MOVE events keep going to the right window and to the spy
3010 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3011 .deviceId(touchDeviceId)
3012 .pointer(PointerBuilder(0, ToolType::FINGER).x(310).y(110))
3013 .build());
3014 rightWindow->consumeMotionEvent(
3015 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3016 spyWindow->consumeMotionEvent(
3017 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3018
3019 spyWindow->assertNoEvents();
3020 leftWindow->assertNoEvents();
3021 rightWindow->assertNoEvents();
3022}
3023
3024/**
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003025 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3026 * both.
3027 * Check hover in left window and touch down in the right window.
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003028 * At first, spy should receive hover. Spy shouldn't receive touch while stylus is hovering.
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003029 * At the same time, left and right should be getting independent streams of hovering and touch,
3030 * respectively.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003031 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003032TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverBlocksTouchWithSpy) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003033 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003034 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3035
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003036 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3037 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003038 spyWindow->setFrame(Rect(0, 0, 400, 400));
3039 spyWindow->setTrustedOverlay(true);
3040 spyWindow->setSpy(true);
3041
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003042 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3043 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003044 leftWindow->setFrame(Rect(0, 0, 200, 200));
3045
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003046 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3047 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003048 rightWindow->setFrame(Rect(200, 0, 400, 200));
3049
3050 mDispatcher->onWindowInfosChanged(
3051 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3052
3053 const int32_t stylusDeviceId = 1;
3054 const int32_t touchDeviceId = 2;
3055
3056 // Stylus hover on the left window
3057 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3058 .deviceId(stylusDeviceId)
3059 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3060 .build());
3061 leftWindow->consumeMotionEvent(
3062 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3063 spyWindow->consumeMotionEvent(
3064 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3065
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003066 // Touch down on the right window. Spy doesn't receive this touch because it already has
3067 // stylus hovering there.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003068 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3069 .deviceId(touchDeviceId)
3070 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3071 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003072 leftWindow->assertNoEvents();
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003073 spyWindow->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003074 rightWindow->consumeMotionEvent(
3075 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3076
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003077 // Stylus movements continue. They should be delivered to the left window and the spy.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003078 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3079 .deviceId(stylusDeviceId)
3080 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3081 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003082 leftWindow->consumeMotionEvent(
3083 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003084 spyWindow->consumeMotionEvent(
3085 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003086
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003087 // Touch movements continue. They should be delivered to the right window only
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003088 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3089 .deviceId(touchDeviceId)
3090 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3091 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003092 rightWindow->consumeMotionEvent(
3093 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3094
3095 spyWindow->assertNoEvents();
3096 leftWindow->assertNoEvents();
3097 rightWindow->assertNoEvents();
3098}
3099
3100/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003101 * Three windows: a window on the left, a window on the right, and a spy window positioned above
3102 * both.
3103 * Check hover in left window and touch down in the right window.
3104 * At first, spy should receive hover. Next, spy should receive touch.
3105 * At the same time, left and right should be getting independent streams of hovering and touch,
3106 * respectively.
3107 */
3108TEST_F(InputDispatcherMultiDeviceTest, MultiDeviceHoverDoesNotBlockTouchWithSpy) {
3109 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3110 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3111
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003112 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3113 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003114 spyWindow->setFrame(Rect(0, 0, 400, 400));
3115 spyWindow->setTrustedOverlay(true);
3116 spyWindow->setSpy(true);
3117
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003118 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3119 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003120 leftWindow->setFrame(Rect(0, 0, 200, 200));
3121
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003122 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3123 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003124 rightWindow->setFrame(Rect(200, 0, 400, 200));
3125
3126 mDispatcher->onWindowInfosChanged(
3127 {{*spyWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3128
3129 const int32_t stylusDeviceId = 1;
3130 const int32_t touchDeviceId = 2;
3131
3132 // Stylus hover on the left window
3133 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3134 .deviceId(stylusDeviceId)
3135 .pointer(PointerBuilder(0, ToolType::STYLUS).x(100).y(100))
3136 .build());
3137 leftWindow->consumeMotionEvent(
3138 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3139 spyWindow->consumeMotionEvent(
3140 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3141
3142 // Touch down on the right window.
3143 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3144 .deviceId(touchDeviceId)
3145 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3146 .build());
3147 leftWindow->assertNoEvents();
3148 spyWindow->consumeMotionEvent(
3149 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3150 rightWindow->consumeMotionEvent(
3151 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3152
3153 // Stylus movements continue. They should be delivered to the left window and the spy.
3154 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3155 .deviceId(stylusDeviceId)
3156 .pointer(PointerBuilder(0, ToolType::STYLUS).x(110).y(110))
3157 .build());
3158 leftWindow->consumeMotionEvent(
3159 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3160 spyWindow->consumeMotionEvent(
3161 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3162
3163 // Touch movements continue. They should be delivered to the right window and the spy
3164 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3165 .deviceId(touchDeviceId)
3166 .pointer(PointerBuilder(0, ToolType::FINGER).x(301).y(101))
3167 .build());
3168 rightWindow->consumeMotionEvent(
3169 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3170 spyWindow->consumeMotionEvent(
3171 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
3172
3173 spyWindow->assertNoEvents();
3174 leftWindow->assertNoEvents();
3175 rightWindow->assertNoEvents();
3176}
3177
3178/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003179 * On a single window, use two different devices: mouse and touch.
3180 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3181 * Mouse is clicked next, which causes the touch stream to be aborted with ACTION_CANCEL.
3182 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is ignored,
3183 * because the mouse is currently down, and a POINTER_DOWN event from the touchscreen does not
3184 * represent a new gesture.
3185 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003186TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown_legacy) {
3187 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003188 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003189 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3190 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003191 window->setFrame(Rect(0, 0, 400, 400));
3192
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003193 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003194
3195 const int32_t touchDeviceId = 4;
3196 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003197
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08003198 // First touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003199 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3200 .deviceId(touchDeviceId)
3201 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3202 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003203 // Second touch pointer down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003204 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3205 .deviceId(touchDeviceId)
3206 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3207 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3208 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003209 // First touch pointer lifts. The second one remains down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003210 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3211 .deviceId(touchDeviceId)
3212 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3213 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3214 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003215 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3216 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3217 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3218
3219 // Mouse down. The touch should be canceled
Prabir Pradhan678438e2023-04-13 19:32:51 +00003220 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3221 .deviceId(mouseDeviceId)
3222 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3223 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3224 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003225
3226 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
Siarhei Vishniakou82dc0422023-02-17 23:12:52 -08003227 WithPointerCount(1u)));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003228 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3229
Prabir Pradhan678438e2023-04-13 19:32:51 +00003230 mDispatcher->notifyMotion(
3231 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3232 .deviceId(mouseDeviceId)
3233 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3234 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3235 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3236 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003237 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3238
3239 // Second touch pointer down.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003240 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3241 .deviceId(touchDeviceId)
3242 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3243 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3244 .build());
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003245 // Since we already canceled this touch gesture, it will be ignored until a completely new
3246 // gesture is started. This is easier to implement than trying to keep track of the new pointer
3247 // and generating an ACTION_DOWN instead of ACTION_POINTER_DOWN.
3248 // However, mouse movements should continue to work.
3249 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3250 .deviceId(mouseDeviceId)
3251 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3252 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3253 .build());
3254 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3255
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003256 window->assertNoEvents();
3257}
3258
3259/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003260 * On a single window, use two different devices: mouse and touch.
3261 * Touch happens first, with two pointers going down, and then the first pointer leaving.
3262 * Mouse is clicked next, which should not interfere with the touch stream.
3263 * Finally, a second touch pointer goes down again. Ensure the second touch pointer is also
3264 * delivered correctly.
3265 */
3266TEST_F(InputDispatcherMultiDeviceTest, MixedTouchAndMouseWithPointerDown) {
3267 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3268 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003269 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3270 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003271 window->setFrame(Rect(0, 0, 400, 400));
3272
3273 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3274
3275 const int32_t touchDeviceId = 4;
3276 const int32_t mouseDeviceId = 6;
3277
3278 // First touch pointer down
3279 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3280 .deviceId(touchDeviceId)
3281 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3282 .build());
3283 // Second touch pointer down
3284 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3285 .deviceId(touchDeviceId)
3286 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3287 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3288 .build());
3289 // First touch pointer lifts. The second one remains down
3290 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
3291 .deviceId(touchDeviceId)
3292 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3293 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3294 .build());
3295 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3296 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
3297 window->consumeMotionEvent(WithMotionAction(POINTER_0_UP));
3298
3299 // Mouse down
3300 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3301 .deviceId(mouseDeviceId)
3302 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3303 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3304 .build());
3305
3306 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
3307
3308 mDispatcher->notifyMotion(
3309 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
3310 .deviceId(mouseDeviceId)
3311 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3312 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
3313 .pointer(PointerBuilder(0, ToolType::MOUSE).x(320).y(100))
3314 .build());
3315 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
3316
3317 // Second touch pointer down.
3318 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3319 .deviceId(touchDeviceId)
3320 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3321 .pointer(PointerBuilder(1, ToolType::FINGER).x(350).y(100))
3322 .build());
3323 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_0_DOWN), WithDeviceId(touchDeviceId),
3324 WithPointerCount(2u)));
3325
3326 // Mouse movements should continue to work
3327 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
3328 .deviceId(mouseDeviceId)
3329 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3330 .pointer(PointerBuilder(0, ToolType::MOUSE).x(330).y(110))
3331 .build());
3332 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
3333
3334 window->assertNoEvents();
3335}
3336
3337/**
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003338 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event cancels
3339 * the injected event.
3340 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003341TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent_legacy) {
3342 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003343 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003344 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3345 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003346 window->setFrame(Rect(0, 0, 400, 400));
3347
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003348 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003349
3350 const int32_t touchDeviceId = 4;
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003351 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3352 // completion.
3353 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003354 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003355 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3356 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003357 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003358 .build()));
3359 window->consumeMotionEvent(
3360 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3361
3362 // Now a real touch comes. Rather than crashing or dropping the real event, the injected pointer
3363 // should be canceled and the new gesture should take over.
Prabir Pradhan678438e2023-04-13 19:32:51 +00003364 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3365 .deviceId(touchDeviceId)
3366 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3367 .build());
Siarhei Vishniakou56e79092023-02-21 19:13:16 -08003368
3369 window->consumeMotionEvent(
3370 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3371 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3372}
3373
3374/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003375 * Inject a touch down and then send a new event via 'notifyMotion'. Ensure the new event runs
3376 * parallel to the injected event.
3377 */
3378TEST_F(InputDispatcherMultiDeviceTest, UnfinishedInjectedEvent) {
3379 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3380 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003381 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3382 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003383 window->setFrame(Rect(0, 0, 400, 400));
3384
3385 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3386
3387 const int32_t touchDeviceId = 4;
3388 // Pretend a test injects an ACTION_DOWN mouse event, but forgets to lift up the touch after
3389 // completion.
3390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
3391 injectMotionEvent(*mDispatcher,
3392 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3393 .deviceId(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID)
3394 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3395 .build()));
3396 window->consumeMotionEvent(
3397 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(VIRTUAL_KEYBOARD_ID)));
3398
3399 // Now a real touch comes. The injected pointer will remain, and the new gesture will also be
3400 // allowed through.
3401 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3402 .deviceId(touchDeviceId)
3403 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3404 .build());
3405 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3406}
3407
3408/**
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003409 * This test is similar to the test above, but the sequence of injected events is different.
3410 *
3411 * Two windows: a window on the left and a window on the right.
3412 * Mouse is hovered over the left window.
3413 * Next, we tap on the left window, where the cursor was last seen.
3414 *
3415 * After that, we inject one finger down onto the right window, and then a second finger down onto
3416 * the left window.
3417 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3418 * window (first), and then another on the left window (second).
3419 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3420 * In the buggy implementation, second finger down on the left window would cause a crash.
3421 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003422TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch_legacy) {
3423 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003424 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003425 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3426 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003427 leftWindow->setFrame(Rect(0, 0, 200, 200));
3428
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003429 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3430 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003431 rightWindow->setFrame(Rect(200, 0, 400, 200));
3432
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003433 mDispatcher->onWindowInfosChanged(
3434 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003435
3436 const int32_t mouseDeviceId = 6;
3437 const int32_t touchDeviceId = 4;
3438 // Hover over the left window. Keep the cursor there.
3439 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003440 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003441 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
3442 AINPUT_SOURCE_MOUSE)
3443 .deviceId(mouseDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003444 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003445 .build()));
3446 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3447
3448 // Tap on left window
3449 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003450 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003451 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3452 AINPUT_SOURCE_TOUCHSCREEN)
3453 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003454 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003455 .build()));
3456
3457 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003458 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003459 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3460 AINPUT_SOURCE_TOUCHSCREEN)
3461 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003462 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003463 .build()));
3464 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
3465 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3466 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_UP));
3467
3468 // First finger down on right window
3469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003470 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003471 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
3472 AINPUT_SOURCE_TOUCHSCREEN)
3473 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003474 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003475 .build()));
3476 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3477
3478 // Second finger down on the left window
3479 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003480 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003481 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3482 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003483 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3484 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou6464e462023-02-06 18:57:59 -08003485 .build()));
3486 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3487 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3488
3489 // No more events
3490 leftWindow->assertNoEvents();
3491 rightWindow->assertNoEvents();
3492}
3493
3494/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003495 * This test is similar to the test above, but the sequence of injected events is different.
3496 *
3497 * Two windows: a window on the left and a window on the right.
3498 * Mouse is hovered over the left window.
3499 * Next, we tap on the left window, where the cursor was last seen.
3500 *
3501 * After that, we send one finger down onto the right window, and then a second finger down onto
3502 * the left window.
3503 * The touch is split, so this last gesture should cause 2 ACTION_DOWN events, one in the right
3504 * window (first), and then another on the left window (second).
3505 * This test reproduces a crash where there is a mismatch between the downTime and eventTime.
3506 * In the buggy implementation, second finger down on the left window would cause a crash.
3507 */
3508TEST_F(InputDispatcherMultiDeviceTest, HoverTapAndSplitTouch) {
3509 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3510 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003511 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
3512 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003513 leftWindow->setFrame(Rect(0, 0, 200, 200));
3514
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003515 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
3516 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003517 rightWindow->setFrame(Rect(200, 0, 400, 200));
3518
3519 mDispatcher->onWindowInfosChanged(
3520 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
3521
3522 const int32_t mouseDeviceId = 6;
3523 const int32_t touchDeviceId = 4;
3524 // Hover over the left window. Keep the cursor there.
3525 mDispatcher->notifyMotion(
3526 MotionArgsBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3527 .deviceId(mouseDeviceId)
3528 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
3529 .build());
3530 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
3531
3532 // Tap on left window
3533 mDispatcher->notifyMotion(
3534 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3535 .deviceId(touchDeviceId)
3536 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3537 .build());
3538
3539 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3540 .deviceId(touchDeviceId)
3541 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3542 .build());
3543 leftWindow->consumeMotionEvent(
3544 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithDeviceId(touchDeviceId)));
3545 leftWindow->consumeMotionEvent(
3546 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithDeviceId(touchDeviceId)));
3547
3548 // First finger down on right window
3549 mDispatcher->notifyMotion(
3550 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3551 .deviceId(touchDeviceId)
3552 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3553 .build());
3554 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3555
3556 // Second finger down on the left window
3557 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3558 .deviceId(touchDeviceId)
3559 .pointer(PointerBuilder(0, ToolType::FINGER).x(300).y(100))
3560 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
3561 .build());
3562 leftWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_DOWN));
3563 rightWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_MOVE));
3564
3565 // No more events
3566 leftWindow->assertNoEvents();
3567 rightWindow->assertNoEvents();
3568}
3569
3570/**
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003571 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3572 * While the touch is down, new hover events from the stylus device should be ignored. After the
3573 * touch is gone, stylus hovering should start working again.
3574 */
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003575TEST_F(InputDispatcherMultiDeviceTest, StylusHoverIgnoresTouchTap) {
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003576 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003577 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003578 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3579 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003580 window->setFrame(Rect(0, 0, 200, 200));
3581
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003582 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003583
3584 const int32_t stylusDeviceId = 5;
3585 const int32_t touchDeviceId = 4;
3586 // Start hovering with stylus
3587 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003588 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003589 MotionEventBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003590 .deviceId(stylusDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003591 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003592 .build()));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003593 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003594
3595 // Finger down on the window
3596 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003597 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07003598 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003599 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003600 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003601 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003602 // The touch device should be ignored!
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003603
Siarhei Vishniakou2899c552023-07-10 18:20:46 -07003604 // Continue hovering with stylus.
3605 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003606 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003607 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3608 AINPUT_SOURCE_STYLUS)
3609 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003610 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003611 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003612 // Hovers continue to work
3613 window->consumeMotionEvent(
3614 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003615
3616 // Lift up the finger
3617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003618 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003619 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
3620 AINPUT_SOURCE_TOUCHSCREEN)
3621 .deviceId(touchDeviceId)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003622 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003623 .build()));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003624
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003625 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07003626 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003627 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
3628 AINPUT_SOURCE_STYLUS)
3629 .deviceId(stylusDeviceId)
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07003630 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003631 .build()));
Siarhei Vishniakou3ad54f52023-11-02 16:54:40 -07003632 window->consumeMotionEvent(
3633 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou2e3e4432023-02-09 18:34:11 -08003634 window->assertNoEvents();
3635}
3636
3637/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003638 * Start hovering with a stylus device, and then tap with a touch device. Ensure no crash occurs.
3639 * While the touch is down, hovering from the stylus is not affected. After the touch is gone,
3640 * check that the stylus hovering continues to work.
3641 */
3642TEST_F(InputDispatcherMultiDeviceTest, StylusHoverWithTouchTap) {
3643 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
3644 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003645 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3646 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003647 window->setFrame(Rect(0, 0, 200, 200));
3648
3649 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3650
3651 const int32_t stylusDeviceId = 5;
3652 const int32_t touchDeviceId = 4;
3653 // Start hovering with stylus
3654 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3655 .deviceId(stylusDeviceId)
3656 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3657 .build());
3658 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3659
3660 // Finger down on the window
3661 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3662 .deviceId(touchDeviceId)
3663 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3664 .build());
3665 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3666
3667 // Continue hovering with stylus.
3668 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3669 .deviceId(stylusDeviceId)
3670 .pointer(PointerBuilder(0, ToolType::STYLUS).x(60).y(60))
3671 .build());
3672 // Hovers continue to work
3673 window->consumeMotionEvent(
3674 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3675
3676 // Lift up the finger
3677 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3678 .deviceId(touchDeviceId)
3679 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
3680 .build());
3681 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(touchDeviceId)));
3682
3683 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3684 .deviceId(stylusDeviceId)
3685 .pointer(PointerBuilder(0, ToolType::STYLUS).x(70).y(70))
3686 .build());
3687 window->consumeMotionEvent(
3688 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3689 window->assertNoEvents();
3690}
3691
3692/**
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003693 * If stylus is down anywhere on the screen, then touches should not be delivered to windows that
3694 * have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3695 *
3696 * Two windows: one on the left and one on the right.
3697 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3698 * Stylus down on the left window, and then touch down on the right window.
3699 * Check that the right window doesn't get touches while the stylus is down on the left window.
3700 */
3701TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusDownBlocksTouch) {
3702 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3703 sp<FakeWindowHandle> leftWindow =
3704 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003705 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003706 leftWindow->setFrame(Rect(0, 0, 100, 100));
3707
3708 sp<FakeWindowHandle> sbtRightWindow =
3709 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003710 "Stylus blocks touch (right) window",
3711 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003712 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3713 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3714
3715 mDispatcher->onWindowInfosChanged(
3716 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3717
3718 const int32_t stylusDeviceId = 5;
3719 const int32_t touchDeviceId = 4;
3720
3721 // Stylus down in the left window
3722 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3723 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3724 .deviceId(stylusDeviceId)
3725 .build());
3726 leftWindow->consumeMotionEvent(
3727 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
3728
3729 // Finger tap on the right window
3730 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3731 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3732 .deviceId(touchDeviceId)
3733 .build());
3734 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3735 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3736 .deviceId(touchDeviceId)
3737 .build());
3738
3739 // The touch should be blocked, because stylus is down somewhere else on screen!
3740 sbtRightWindow->assertNoEvents();
3741
3742 // Continue stylus motion, and ensure it's not impacted.
3743 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_STYLUS)
3744 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3745 .deviceId(stylusDeviceId)
3746 .build());
3747 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3748 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3749 .deviceId(stylusDeviceId)
3750 .build());
3751 leftWindow->consumeMotionEvent(
3752 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
3753 leftWindow->consumeMotionEvent(
3754 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(stylusDeviceId)));
3755
3756 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3757 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3758 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3759 .deviceId(touchDeviceId)
3760 .build());
3761 sbtRightWindow->consumeMotionEvent(
3762 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3763}
3764
3765/**
3766 * If stylus is hovering anywhere on the screen, then touches should not be delivered to windows
3767 * that have InputConfig::GLOBAL_STYLUS_BLOCKS_TOUCH.
3768 *
3769 * Two windows: one on the left and one on the right.
3770 * The window on the right has GLOBAL_STYLUS_BLOCKS_TOUCH config.
3771 * Stylus hover on the left window, and then touch down on the right window.
3772 * Check that the right window doesn't get touches while the stylus is hovering on the left window.
3773 */
3774TEST_F(InputDispatcherMultiDeviceTest, GlobalStylusHoverBlocksTouch) {
3775 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3776 sp<FakeWindowHandle> leftWindow =
3777 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003778 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003779 leftWindow->setFrame(Rect(0, 0, 100, 100));
3780
3781 sp<FakeWindowHandle> sbtRightWindow =
3782 sp<FakeWindowHandle>::make(application, mDispatcher,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003783 "Stylus blocks touch (right) window",
3784 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf77f60a2023-10-23 17:26:05 -07003785 sbtRightWindow->setFrame(Rect(100, 100, 200, 200));
3786 sbtRightWindow->setGlobalStylusBlocksTouch(true);
3787
3788 mDispatcher->onWindowInfosChanged(
3789 {{*leftWindow->getInfo(), *sbtRightWindow->getInfo()}, {}, 0, 0});
3790
3791 const int32_t stylusDeviceId = 5;
3792 const int32_t touchDeviceId = 4;
3793
3794 // Stylus hover in the left window
3795 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3796 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(52))
3797 .deviceId(stylusDeviceId)
3798 .build());
3799 leftWindow->consumeMotionEvent(
3800 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(stylusDeviceId)));
3801
3802 // Finger tap on the right window
3803 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3804 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3805 .deviceId(touchDeviceId)
3806 .build());
3807 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
3808 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(151))
3809 .deviceId(touchDeviceId)
3810 .build());
3811
3812 // The touch should be blocked, because stylus is hovering somewhere else on screen!
3813 sbtRightWindow->assertNoEvents();
3814
3815 // Continue stylus motion, and ensure it's not impacted.
3816 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
3817 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3818 .deviceId(stylusDeviceId)
3819 .build());
3820 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3821 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(53))
3822 .deviceId(stylusDeviceId)
3823 .build());
3824 leftWindow->consumeMotionEvent(
3825 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithDeviceId(stylusDeviceId)));
3826 leftWindow->consumeMotionEvent(
3827 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(stylusDeviceId)));
3828
3829 // Now that the stylus gesture is done, touches should be getting delivered correctly.
3830 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3831 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(153))
3832 .deviceId(touchDeviceId)
3833 .build());
3834 sbtRightWindow->consumeMotionEvent(
3835 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
3836}
3837
3838/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003839 * A spy window above a window with no input channel.
3840 * Start hovering with a stylus device, and then tap with it.
3841 * Ensure spy window receives the entire sequence.
3842 */
3843TEST_F(InputDispatcherTest, StylusHoverAndDownNoInputChannel) {
3844 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003845 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3846 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003847 spyWindow->setFrame(Rect(0, 0, 200, 200));
3848 spyWindow->setTrustedOverlay(true);
3849 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003850 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3851 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003852 window->setNoInputChannel(true);
3853 window->setFrame(Rect(0, 0, 200, 200));
3854
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003855 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003856
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003857 // Start hovering with stylus
Prabir Pradhan678438e2023-04-13 19:32:51 +00003858 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3859 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3860 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003861 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3862 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003863 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3864 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3865 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003866 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3867
3868 // Stylus touches down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003869 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_STYLUS)
3870 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3871 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003872 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3873
3874 // Stylus goes up
Prabir Pradhan678438e2023-04-13 19:32:51 +00003875 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_STYLUS)
3876 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3877 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003878 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
3879
3880 // Again hover
Prabir Pradhan678438e2023-04-13 19:32:51 +00003881 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3882 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3883 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003884 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3885 // Stop hovering
Prabir Pradhan678438e2023-04-13 19:32:51 +00003886 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3887 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3888 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003889 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3890
3891 // No more events
3892 spyWindow->assertNoEvents();
3893 window->assertNoEvents();
3894}
3895
3896/**
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003897 * A stale stylus HOVER_EXIT event is injected. Since it's a stale event, it should generally be
3898 * rejected. But since we already have an ongoing gesture, this event should be processed.
3899 * This prevents inconsistent events being handled inside the dispatcher.
3900 */
3901TEST_F(InputDispatcherTest, StaleStylusHoverGestureIsComplete) {
3902 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
3903
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003904 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3905 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou6b71b632023-10-27 21:34:46 -07003906 window->setFrame(Rect(0, 0, 200, 200));
3907
3908 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
3909
3910 // Start hovering with stylus
3911 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3912 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3913 .build());
3914 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3915
3916 NotifyMotionArgs hoverExit = MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
3917 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
3918 .build();
3919 // Make this 'hoverExit' event stale
3920 mFakePolicy->setStaleEventTimeout(100ms);
3921 std::this_thread::sleep_for(100ms);
3922
3923 // It shouldn't be dropped by the dispatcher, even though it's stale.
3924 mDispatcher->notifyMotion(hoverExit);
3925 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3926
3927 // Stylus starts hovering again! There should be no crash.
3928 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
3929 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(51))
3930 .build());
3931 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
3932}
3933
3934/**
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003935 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
3936 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
3937 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
3938 * While the mouse is down, new move events from the touch device should be ignored.
3939 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07003940TEST_F(InputDispatcherTest, TouchPilferAndMouseMove_legacy) {
3941 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003942 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003943 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
3944 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003945 spyWindow->setFrame(Rect(0, 0, 200, 200));
3946 spyWindow->setTrustedOverlay(true);
3947 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07003948 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
3949 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003950 window->setFrame(Rect(0, 0, 200, 200));
3951
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07003952 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003953
3954 const int32_t mouseDeviceId = 7;
3955 const int32_t touchDeviceId = 4;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003956
3957 // Hover a bit with mouse first
Prabir Pradhan678438e2023-04-13 19:32:51 +00003958 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
3959 .deviceId(mouseDeviceId)
3960 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3961 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003962 spyWindow->consumeMotionEvent(
3963 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3964 window->consumeMotionEvent(
3965 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
3966
3967 // Start touching
Prabir Pradhan678438e2023-04-13 19:32:51 +00003968 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
3969 .deviceId(touchDeviceId)
3970 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
3971 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003972 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3973 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
3974 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3975 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
3976
Prabir Pradhan678438e2023-04-13 19:32:51 +00003977 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3978 .deviceId(touchDeviceId)
3979 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
3980 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003981 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3982 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3983
3984 // Pilfer the stream
3985 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
3986 window->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
3987
Prabir Pradhan678438e2023-04-13 19:32:51 +00003988 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
3989 .deviceId(touchDeviceId)
3990 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
3991 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08003992 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
3993
3994 // Mouse down
Prabir Pradhan678438e2023-04-13 19:32:51 +00003995 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
3996 .deviceId(mouseDeviceId)
3997 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
3998 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
3999 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004000
4001 spyWindow->consumeMotionEvent(
4002 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
4003 spyWindow->consumeMotionEvent(
4004 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4005 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4006
Prabir Pradhan678438e2023-04-13 19:32:51 +00004007 mDispatcher->notifyMotion(
4008 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4009 .deviceId(mouseDeviceId)
4010 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4011 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4012 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4013 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004014 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4015 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4016
4017 // Mouse move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00004018 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4019 .deviceId(mouseDeviceId)
4020 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4021 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4022 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004023 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4024 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4025
4026 // Touch move!
Prabir Pradhan678438e2023-04-13 19:32:51 +00004027 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4028 .deviceId(touchDeviceId)
4029 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4030 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004031
4032 // No more events
4033 spyWindow->assertNoEvents();
4034 window->assertNoEvents();
4035}
4036
4037/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004038 * Start hovering with a mouse, and then tap with a touch device. Pilfer the touch stream.
4039 * Next, click with the mouse device. Both windows (spy and regular) should receive the new mouse
4040 * ACTION_DOWN event because that's a new gesture, and pilfering should no longer be active.
4041 * While the mouse is down, new move events from the touch device should continue to work.
4042 */
4043TEST_F(InputDispatcherTest, TouchPilferAndMouseMove) {
4044 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4045 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004046 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4047 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004048 spyWindow->setFrame(Rect(0, 0, 200, 200));
4049 spyWindow->setTrustedOverlay(true);
4050 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004051 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4052 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004053 window->setFrame(Rect(0, 0, 200, 200));
4054
4055 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4056
4057 const int32_t mouseDeviceId = 7;
4058 const int32_t touchDeviceId = 4;
4059
4060 // Hover a bit with mouse first
4061 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4062 .deviceId(mouseDeviceId)
4063 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4064 .build());
4065 spyWindow->consumeMotionEvent(
4066 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4067 window->consumeMotionEvent(
4068 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4069
4070 // Start touching
4071 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4072 .deviceId(touchDeviceId)
4073 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4074 .build());
4075
4076 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4077 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4078
4079 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4080 .deviceId(touchDeviceId)
4081 .pointer(PointerBuilder(0, ToolType::FINGER).x(55).y(55))
4082 .build());
4083 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4084 window->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4085
4086 // Pilfer the stream
4087 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4088 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
4089 // Hover is not pilfered! Only touch.
4090
4091 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4092 .deviceId(touchDeviceId)
4093 .pointer(PointerBuilder(0, ToolType::FINGER).x(60).y(60))
4094 .build());
4095 spyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
4096
4097 // Mouse down
4098 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4099 .deviceId(mouseDeviceId)
4100 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4101 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4102 .build());
4103
4104 spyWindow->consumeMotionEvent(
4105 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4106 spyWindow->consumeMotionEvent(
4107 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4108 window->consumeMotionEvent(
4109 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4110 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4111
4112 mDispatcher->notifyMotion(
4113 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4114 .deviceId(mouseDeviceId)
4115 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4116 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4117 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4118 .build());
4119 spyWindow->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4120 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4121
4122 // Mouse move!
4123 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
4124 .deviceId(mouseDeviceId)
4125 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4126 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4127 .build());
4128 spyWindow->consumeMotionEvent(
4129 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4130 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(mouseDeviceId)));
4131
4132 // Touch move!
4133 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4134 .deviceId(touchDeviceId)
4135 .pointer(PointerBuilder(0, ToolType::FINGER).x(65).y(65))
4136 .build());
4137 spyWindow->consumeMotionEvent(
4138 AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4139
4140 // No more events
4141 spyWindow->assertNoEvents();
4142 window->assertNoEvents();
4143}
4144
4145/**
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004146 * On the display, have a single window, and also an area where there's no window.
4147 * First pointer touches the "no window" area of the screen. Second pointer touches the window.
4148 * Make sure that the window receives the second pointer, and first pointer is simply ignored.
4149 */
4150TEST_F(InputDispatcherTest, SplitWorksWhenEmptyAreaIsTouched) {
4151 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4152 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004153 sp<FakeWindowHandle>::make(application, mDispatcher, "Window", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004154
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004155 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004156
4157 // Touch down on the empty space
Prabir Pradhan678438e2023-04-13 19:32:51 +00004158 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{-1, -1}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004159
4160 mDispatcher->waitForIdle();
4161 window->assertNoEvents();
4162
4163 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004164 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{-1, -1}, {10, 10}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004165 mDispatcher->waitForIdle();
4166 window->consumeMotionDown();
4167}
4168
4169/**
4170 * Same test as above, but instead of touching the empty space, the first touch goes to
4171 * non-touchable window.
4172 */
4173TEST_F(InputDispatcherTest, SplitWorksWhenNonTouchableWindowIsTouched) {
4174 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4175 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004176 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004177 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4178 window1->setTouchable(false);
4179 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004180 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004181 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4182
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004183 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004184
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004185 // Touch down on the non-touchable window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004186 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004187
4188 mDispatcher->waitForIdle();
4189 window1->assertNoEvents();
4190 window2->assertNoEvents();
4191
4192 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004193 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -08004194 mDispatcher->waitForIdle();
4195 window2->consumeMotionDown();
4196}
4197
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004198/**
4199 * When splitting touch events the downTime should be adjusted such that the downTime corresponds
4200 * to the event time of the first ACTION_DOWN sent to the particular window.
4201 */
4202TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
4203 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4204 sp<FakeWindowHandle> window1 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004205 sp<FakeWindowHandle>::make(application, mDispatcher, "Window1", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004206 window1->setTouchableRegion(Region{{0, 0, 100, 100}});
4207 sp<FakeWindowHandle> window2 =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07004208 sp<FakeWindowHandle>::make(application, mDispatcher, "Window2", DISPLAY_ID);
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004209 window2->setTouchableRegion(Region{{100, 0, 200, 100}});
4210
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004211 mDispatcher->onWindowInfosChanged({{*window1->getInfo(), *window2->getInfo()}, {}, 0, 0});
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004212
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004213 // Touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004214 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004215 mDispatcher->waitForIdle();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004216
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004217 const std::unique_ptr<MotionEvent> firstDown =
4218 window1->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4219 ASSERT_EQ(firstDown->getDownTime(), firstDown->getEventTime());
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004220 window2->assertNoEvents();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004221
4222 // Now touch down on the window with another pointer
Prabir Pradhan678438e2023-04-13 19:32:51 +00004223 mDispatcher->notifyMotion(generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004224 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004225
4226 const std::unique_ptr<MotionEvent> secondDown =
4227 window2->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
4228 ASSERT_EQ(secondDown->getDownTime(), secondDown->getEventTime());
4229 ASSERT_NE(firstDown->getDownTime(), secondDown->getDownTime());
4230 // We currently send MOVE events to all windows receiving a split touch when there is any change
4231 // in the touch state, even when none of the pointers in the split window actually moved.
4232 // Document this behavior in the test.
4233 window1->consumeMotionMove();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004234
4235 // Now move the pointer on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004236 mDispatcher->notifyMotion(generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004237 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004238
4239 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4240 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004241
4242 // Now add new touch down on the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004243 mDispatcher->notifyMotion(generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004244 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004245
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004246 window2->consumeMotionEvent(
4247 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(secondDown->getDownTime())));
4248 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004249
4250 // Now move the pointer on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004251 mDispatcher->notifyMotion(
4252 generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}, {150, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004253 mDispatcher->waitForIdle();
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004254
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004255 window1->consumeMotionEvent(WithDownTime(firstDown->getDownTime()));
4256 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
4257
4258 // Now add new touch down on the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00004259 mDispatcher->notifyMotion(
4260 generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}}));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004261 mDispatcher->waitForIdle();
Prabir Pradhan9d5f9ce2024-01-24 00:03:41 +00004262
4263 window1->consumeMotionEvent(
4264 AllOf(WithMotionAction(POINTER_1_DOWN), WithDownTime(firstDown->getDownTime())));
4265 window2->consumeMotionEvent(WithDownTime(secondDown->getDownTime()));
Vaibhav Devmurari882bd9b2022-06-23 14:54:54 +00004266}
4267
Garfield Tandf26e862020-07-01 20:18:19 -07004268TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004269 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004270 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
4271 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004272 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004273 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
4274 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004275 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004276
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004277 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004278
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004279 mDispatcher->onWindowInfosChanged(
4280 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004281
4282 // Start cursor position in right window so that we can move the cursor to left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004283 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004284 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004285 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4286 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004287 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004288 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004289 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004290
4291 // Move cursor into left window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004292 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004293 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004294 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4295 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004296 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004297 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004298 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4299 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004300
4301 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004302 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004303 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004304 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4305 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004306 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004307 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004308 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4309 windowLeft->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004310
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004311 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004312 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004313 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4314 AINPUT_SOURCE_MOUSE)
4315 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4316 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004317 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004318 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004319 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004320
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004321 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004322 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004323 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4324 AINPUT_SOURCE_MOUSE)
4325 .buttonState(0)
4326 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004327 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004328 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004329 windowLeft->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004330
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004331 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004332 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004333 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4334 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004335 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004336 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004337 windowLeft->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004338
4339 // Move mouse cursor back to right window
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004340 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004341 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004342 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4343 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004344 .pointer(PointerBuilder(0, ToolType::MOUSE).x(900).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004345 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004346 windowRight->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004347
4348 // No more events
4349 windowLeft->assertNoEvents();
4350 windowRight->assertNoEvents();
4351}
4352
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004353/**
4354 * Put two fingers down (and don't release them) and click the mouse button.
4355 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4356 * currently active gesture should be canceled, and the new one should proceed.
4357 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004358TEST_F(InputDispatcherTest, TwoPointersDownMouseClick_legacy) {
4359 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004360 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004361 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4362 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004363 window->setFrame(Rect(0, 0, 600, 800));
4364
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004365 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004366
4367 const int32_t touchDeviceId = 4;
4368 const int32_t mouseDeviceId = 6;
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004369
4370 // Two pointers down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004371 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4372 .deviceId(touchDeviceId)
4373 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4374 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004375
Prabir Pradhan678438e2023-04-13 19:32:51 +00004376 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4377 .deviceId(touchDeviceId)
4378 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4379 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4380 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004381 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4382 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4383
4384 // Inject a series of mouse events for a mouse click
Prabir Pradhan678438e2023-04-13 19:32:51 +00004385 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4386 .deviceId(mouseDeviceId)
4387 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4388 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4389 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004390 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId),
4391 WithPointerCount(2u)));
4392 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4393
Prabir Pradhan678438e2023-04-13 19:32:51 +00004394 mDispatcher->notifyMotion(
4395 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4396 .deviceId(mouseDeviceId)
4397 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4398 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4399 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4400 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004401 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4402
4403 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4404 // already canceled gesture, it should be ignored.
Prabir Pradhan678438e2023-04-13 19:32:51 +00004405 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4406 .deviceId(touchDeviceId)
4407 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4408 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4409 .build());
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004410 window->assertNoEvents();
4411}
4412
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004413/**
4414 * Put two fingers down (and don't release them) and click the mouse button.
4415 * The clicking of mouse is a new ACTION_DOWN event. Since it's from a different device, the
4416 * currently active gesture should not be canceled, and the new one should proceed in parallel.
4417 */
4418TEST_F(InputDispatcherTest, TwoPointersDownMouseClick) {
4419 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4420 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004421 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4422 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004423 window->setFrame(Rect(0, 0, 600, 800));
4424
4425 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4426
4427 const int32_t touchDeviceId = 4;
4428 const int32_t mouseDeviceId = 6;
4429
4430 // Two pointers down
4431 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4432 .deviceId(touchDeviceId)
4433 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4434 .build());
4435
4436 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4437 .deviceId(touchDeviceId)
4438 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
4439 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
4440 .build());
4441 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
4442 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
4443
4444 // Send a series of mouse events for a mouse click
4445 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4446 .deviceId(mouseDeviceId)
4447 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4448 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4449 .build());
4450 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(mouseDeviceId)));
4451
4452 mDispatcher->notifyMotion(
4453 MotionArgsBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS, AINPUT_SOURCE_MOUSE)
4454 .deviceId(mouseDeviceId)
4455 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4456 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
4457 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4458 .build());
4459 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
4460
4461 // Try to send more touch events while the mouse is down. Since it's a continuation of an
4462 // already active gesture, it should be sent normally.
4463 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
4464 .deviceId(touchDeviceId)
4465 .pointer(PointerBuilder(0, ToolType::FINGER).x(101).y(101))
4466 .pointer(PointerBuilder(1, ToolType::FINGER).x(121).y(121))
4467 .build());
4468 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
4469 window->assertNoEvents();
4470}
4471
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004472TEST_F(InputDispatcherTest, HoverWithSpyWindows) {
4473 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4474
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004475 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4476 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004477 spyWindow->setFrame(Rect(0, 0, 600, 800));
4478 spyWindow->setTrustedOverlay(true);
4479 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004480 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4481 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004482 window->setFrame(Rect(0, 0, 600, 800));
4483
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004484 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004485 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004486
4487 // Send mouse cursor to the window
4488 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004489 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004490 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4491 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004492 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004493 .build()));
4494
4495 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4496 WithSource(AINPUT_SOURCE_MOUSE)));
4497 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4498 WithSource(AINPUT_SOURCE_MOUSE)));
4499
4500 window->assertNoEvents();
4501 spyWindow->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004502}
4503
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004504TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows_legacy) {
4505 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004506 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4507
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004508 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4509 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004510 spyWindow->setFrame(Rect(0, 0, 600, 800));
4511 spyWindow->setTrustedOverlay(true);
4512 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004513 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4514 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004515 window->setFrame(Rect(0, 0, 600, 800));
4516
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004517 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004518 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004519
4520 // Send mouse cursor to the window
4521 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004522 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004523 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4524 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004525 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004526 .build()));
4527
4528 // Move mouse cursor
4529 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004530 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004531 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4532 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004533 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004534 .build()));
4535
4536 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4537 WithSource(AINPUT_SOURCE_MOUSE)));
4538 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4539 WithSource(AINPUT_SOURCE_MOUSE)));
4540 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4541 WithSource(AINPUT_SOURCE_MOUSE)));
4542 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
4543 WithSource(AINPUT_SOURCE_MOUSE)));
4544 // Touch down on the window
4545 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004546 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004547 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4548 AINPUT_SOURCE_TOUCHSCREEN)
4549 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004550 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004551 .build()));
4552 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4553 WithSource(AINPUT_SOURCE_MOUSE)));
4554 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4555 WithSource(AINPUT_SOURCE_MOUSE)));
4556 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4557 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4558 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4559 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4560
4561 // pilfer the motion, retaining the gesture on the spy window.
4562 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4563 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_CANCEL),
4564 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4565
4566 // Touch UP on the window
4567 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004568 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004569 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4570 AINPUT_SOURCE_TOUCHSCREEN)
4571 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004572 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004573 .build()));
4574 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4575 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4576
4577 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4578 // to send a new gesture. It should again go to both windows (spy and the window below), just
4579 // like the first gesture did, before pilfering. The window configuration has not changed.
4580
4581 // One more tap - DOWN
4582 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004583 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004584 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
4585 AINPUT_SOURCE_TOUCHSCREEN)
4586 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004587 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004588 .build()));
4589 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4590 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4591 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4592 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4593
4594 // Touch UP on the window
4595 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004596 injectMotionEvent(*mDispatcher,
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004597 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
4598 AINPUT_SOURCE_TOUCHSCREEN)
4599 .deviceId(SECOND_DEVICE_ID)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004600 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
Siarhei Vishniakou060f82b2023-01-27 06:39:14 -08004601 .build()));
4602 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4603 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4604 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4605 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4606
4607 window->assertNoEvents();
4608 spyWindow->assertNoEvents();
4609}
4610
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004611TEST_F(InputDispatcherTest, MouseAndTouchWithSpyWindows) {
4612 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4613 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4614
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004615 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
4616 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004617 spyWindow->setFrame(Rect(0, 0, 600, 800));
4618 spyWindow->setTrustedOverlay(true);
4619 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004620 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4621 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004622 window->setFrame(Rect(0, 0, 600, 800));
4623
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004624 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004625 mDispatcher->onWindowInfosChanged({{*spyWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
4626
4627 // Send mouse cursor to the window
4628 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4629 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(100))
4630 .build());
4631
4632 // Move mouse cursor
4633 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4634 .pointer(PointerBuilder(0, ToolType::MOUSE).x(110).y(110))
4635 .build());
4636
4637 window->consumeMotionEvent(
4638 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4639 spyWindow->consumeMotionEvent(
4640 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)));
4641 window->consumeMotionEvent(
4642 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4643 spyWindow->consumeMotionEvent(
4644 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4645 // Touch down on the window
4646 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4647 .deviceId(SECOND_DEVICE_ID)
4648 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4649 .build());
4650 window->consumeMotionEvent(
4651 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4652 spyWindow->consumeMotionEvent(
4653 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4654
4655 // pilfer the motion, retaining the gesture on the spy window.
4656 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindow->getToken()));
4657 window->consumeMotionEvent(
4658 AllOf(WithMotionAction(ACTION_CANCEL), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4659 // Mouse hover is not pilfered
4660
4661 // Touch UP on the window
4662 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4663 .deviceId(SECOND_DEVICE_ID)
4664 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
4665 .build());
4666 spyWindow->consumeMotionEvent(
4667 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4668
4669 // Previously, a touch was pilfered. However, that gesture was just finished. Now, we are going
4670 // to send a new gesture. It should again go to both windows (spy and the window below), just
4671 // like the first gesture did, before pilfering. The window configuration has not changed.
4672
4673 // One more tap - DOWN
4674 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4675 .deviceId(SECOND_DEVICE_ID)
4676 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4677 .build());
4678 window->consumeMotionEvent(
4679 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4680 spyWindow->consumeMotionEvent(
4681 AllOf(WithMotionAction(ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4682
4683 // Touch UP on the window
4684 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4685 .deviceId(SECOND_DEVICE_ID)
4686 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(250))
4687 .build());
4688 window->consumeMotionEvent(
4689 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4690 spyWindow->consumeMotionEvent(
4691 AllOf(WithMotionAction(ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4692
4693 // Mouse movement continues normally as well
4694 // Move mouse cursor
4695 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4696 .pointer(PointerBuilder(0, ToolType::MOUSE).x(120).y(130))
4697 .build());
4698 window->consumeMotionEvent(
4699 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4700 spyWindow->consumeMotionEvent(
4701 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
4702
4703 window->assertNoEvents();
4704 spyWindow->assertNoEvents();
4705}
4706
Garfield Tandf26e862020-07-01 20:18:19 -07004707// This test is different from the test above that HOVER_ENTER and HOVER_EXIT events are injected
4708// directly in this test.
4709TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) {
Chris Yea209fde2020-07-22 13:54:51 -07004710 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004711 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4712 ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004713 window->setFrame(Rect(0, 0, 1200, 800));
Garfield Tandf26e862020-07-01 20:18:19 -07004714
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004715 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tandf26e862020-07-01 20:18:19 -07004716
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004717 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Garfield Tandf26e862020-07-01 20:18:19 -07004718
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004720 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004721 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4722 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004723 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004724 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004725 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Garfield Tandf26e862020-07-01 20:18:19 -07004726 // Inject a series of mouse events for a mouse click
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004727 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004728 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004729 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
4730 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004731 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004732 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004733 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
4734 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Garfield Tandf26e862020-07-01 20:18:19 -07004735
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004736 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004737 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004738 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_PRESS,
4739 AINPUT_SOURCE_MOUSE)
4740 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
4741 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004742 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004743 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004744 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_PRESS));
Garfield Tandf26e862020-07-01 20:18:19 -07004745
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004746 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004747 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004748 MotionEventBuilder(AMOTION_EVENT_ACTION_BUTTON_RELEASE,
4749 AINPUT_SOURCE_MOUSE)
4750 .buttonState(0)
4751 .actionButton(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004752 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004753 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004754 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_BUTTON_RELEASE));
Garfield Tandf26e862020-07-01 20:18:19 -07004755
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08004756 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004757 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004758 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
4759 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004760 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004761 .build()));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004762 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Garfield Tandf26e862020-07-01 20:18:19 -07004763
Siarhei Vishniakoua235c042023-05-02 09:59:09 -07004764 // We already canceled the hovering implicitly by injecting the "DOWN" event without lifting the
4765 // hover first. Therefore, injection of HOVER_EXIT is inconsistent, and should fail.
4766 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004767 injectMotionEvent(*mDispatcher,
Garfield Tandf26e862020-07-01 20:18:19 -07004768 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_EXIT,
4769 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07004770 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Garfield Tandf26e862020-07-01 20:18:19 -07004771 .build()));
Siarhei Vishniakouf372b812023-02-14 18:06:51 -08004772 window->assertNoEvents();
Garfield Tandf26e862020-07-01 20:18:19 -07004773}
4774
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004775/**
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004776 * Hover over a window, and then remove that window. Make sure that HOVER_EXIT for that event
4777 * is generated.
4778 */
4779TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) {
4780 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004781 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4782 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004783 window->setFrame(Rect(0, 0, 1200, 800));
4784
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004785 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004786
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004787 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004788
4789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004790 injectMotionEvent(*mDispatcher,
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004791 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER,
4792 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004793 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004794 .build()));
4795 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4796
4797 // Remove the window, but keep the channel.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004798 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004799 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT));
4800}
4801
4802/**
Daniel Norman7487dfa2023-08-02 16:39:45 -07004803 * Test that invalid HOVER events sent by accessibility do not cause a fatal crash.
4804 */
Ameer Armalycff4fa52023-10-04 23:45:11 +00004805TEST_F_WITH_FLAGS(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash,
4806 REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(com::android::input::flags,
4807 a11y_crash_on_inconsistent_event_stream))) {
Daniel Norman7487dfa2023-08-02 16:39:45 -07004808 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004809 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4810 ui::LogicalDisplayId::DEFAULT);
Daniel Norman7487dfa2023-08-02 16:39:45 -07004811 window->setFrame(Rect(0, 0, 1200, 800));
4812
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004813 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Daniel Norman7487dfa2023-08-02 16:39:45 -07004814
4815 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4816
4817 MotionEventBuilder hoverEnterBuilder =
4818 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4819 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400))
4820 .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
4821 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4822 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4823 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
4824 injectMotionEvent(*mDispatcher, hoverEnterBuilder.build()));
4825 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4826 window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
4827}
4828
4829/**
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004830 * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT.
4831 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004832TEST_F(InputDispatcherTest, TouchDownAfterMouseHover_legacy) {
4833 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004834 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004835 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4836 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004837 window->setFrame(Rect(0, 0, 100, 100));
4838
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004839 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004840
4841 const int32_t mouseDeviceId = 7;
4842 const int32_t touchDeviceId = 4;
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004843
4844 // Start hovering with the mouse
Prabir Pradhan678438e2023-04-13 19:32:51 +00004845 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4846 .deviceId(mouseDeviceId)
4847 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4848 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004849 window->consumeMotionEvent(
4850 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4851
4852 // Touch goes down
Prabir Pradhan678438e2023-04-13 19:32:51 +00004853 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4854 .deviceId(touchDeviceId)
4855 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4856 .build());
Siarhei Vishniakou4e1ffa52023-02-21 11:50:34 -08004857
4858 window->consumeMotionEvent(
4859 AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithDeviceId(mouseDeviceId)));
4860 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4861}
4862
4863/**
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004864 * If mouse is hovering when the touch goes down, the hovering should not be stopped.
4865 */
4866TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) {
4867 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4868 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004869 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4870 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004871 window->setFrame(Rect(0, 0, 100, 100));
4872
4873 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4874
4875 const int32_t mouseDeviceId = 7;
4876 const int32_t touchDeviceId = 4;
4877
4878 // Start hovering with the mouse
4879 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
4880 .deviceId(mouseDeviceId)
4881 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(10))
4882 .build());
4883 window->consumeMotionEvent(
4884 AllOf(WithMotionAction(ACTION_HOVER_ENTER), WithDeviceId(mouseDeviceId)));
4885
4886 // Touch goes down
4887 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4888 .deviceId(touchDeviceId)
4889 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
4890 .build());
4891 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
4892}
4893
4894/**
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004895 * Inject a mouse hover event followed by a tap from touchscreen.
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004896 * The tap causes a HOVER_EXIT event to be generated because the current event
4897 * stream's source has been switched.
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004898 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004899TEST_F(InputDispatcherTest, MouseHoverAndTouchTap_legacy) {
4900 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004901 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004902 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4903 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004904 window->setFrame(Rect(0, 0, 100, 100));
4905
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004906 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004907 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4908 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4909 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004910 ASSERT_NO_FATAL_FAILURE(
4911 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4912 WithSource(AINPUT_SOURCE_MOUSE))));
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004913
4914 // Tap on the window
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004915 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4916 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4917 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004918 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakoub581f7f2022-12-07 20:23:06 +00004919 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4920 WithSource(AINPUT_SOURCE_MOUSE))));
4921
4922 ASSERT_NO_FATAL_FAILURE(
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004923 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4924 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4925
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07004926 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4927 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4928 .build());
Siarhei Vishniakou0b0374d2022-11-17 17:40:53 -08004929 ASSERT_NO_FATAL_FAILURE(
4930 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4931 WithSource(AINPUT_SOURCE_TOUCHSCREEN))));
4932}
4933
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004934/**
4935 * Send a mouse hover event followed by a tap from touchscreen.
4936 * The tap causes a HOVER_EXIT event to be generated because the current event
4937 * stream's source has been switched.
4938 */
4939TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) {
4940 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
4941 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004942 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
4943 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -07004944 window->setFrame(Rect(0, 0, 100, 100));
4945
4946 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
4947 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
4948 .pointer(PointerBuilder(0, ToolType::MOUSE).x(50).y(50))
4949 .build());
4950
4951 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER),
4952 WithSource(AINPUT_SOURCE_MOUSE)));
4953
4954 // Tap on the window
4955 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
4956 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4957 .build());
4958
4959 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_EXIT),
4960 WithSource(AINPUT_SOURCE_MOUSE)));
4961
4962 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN),
4963 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4964
4965 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
4966 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
4967 .build());
4968
4969 window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP),
4970 WithSource(AINPUT_SOURCE_TOUCHSCREEN)));
4971}
4972
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004973TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) {
4974 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
4975 sp<FakeWindowHandle> windowDefaultDisplay =
4976 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004977 ui::LogicalDisplayId::DEFAULT);
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004978 windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800));
4979 sp<FakeWindowHandle> windowSecondDisplay =
4980 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay",
4981 SECOND_DISPLAY_ID);
4982 windowSecondDisplay->setFrame(Rect(0, 0, 600, 800));
4983
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07004984 mDispatcher->onWindowInfosChanged(
4985 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004986
4987 // Set cursor position in window in default display and check that hover enter and move
4988 // events are generated.
4989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004990 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004991 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
4992 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07004993 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07004994 .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(600))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004995 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08004996 windowDefaultDisplay->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02004997
4998 // Remove all windows in secondary display and check that no event happens on window in
4999 // primary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005000 mDispatcher->onWindowInfosChanged({{*windowDefaultDisplay->getInfo()}, {}, 0, 0});
5001
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005002 windowDefaultDisplay->assertNoEvents();
5003
5004 // Move cursor position in window in default display and check that only hover move
5005 // event is generated and not hover enter event.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005006 mDispatcher->onWindowInfosChanged(
5007 {{*windowDefaultDisplay->getInfo(), *windowSecondDisplay->getInfo()}, {}, 0, 0});
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005008 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005009 injectMotionEvent(*mDispatcher,
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005010 MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE,
5011 AINPUT_SOURCE_MOUSE)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005012 .displayId(ui::LogicalDisplayId::DEFAULT)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005013 .pointer(PointerBuilder(0, ToolType::MOUSE).x(400).y(700))
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005014 .build()));
Siarhei Vishniakou5cee1e32022-11-29 12:35:39 -08005015 windowDefaultDisplay->consumeMotionEvent(
5016 AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE),
5017 WithSource(AINPUT_SOURCE_MOUSE)));
Tommy Nordgrendae9dfc2022-10-13 11:25:57 +02005018 windowDefaultDisplay->assertNoEvents();
5019}
5020
Garfield Tan00f511d2019-06-12 16:55:40 -07005021TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) {
Chris Yea209fde2020-07-22 13:54:51 -07005022 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Garfield Tan00f511d2019-06-12 16:55:40 -07005023
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005024 sp<FakeWindowHandle> windowLeft = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
5025 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005026 windowLeft->setFrame(Rect(0, 0, 600, 800));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005027 sp<FakeWindowHandle> windowRight = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
5028 ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005029 windowRight->setFrame(Rect(600, 0, 1200, 800));
Garfield Tan00f511d2019-06-12 16:55:40 -07005030
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005031 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Garfield Tan00f511d2019-06-12 16:55:40 -07005032
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005033 mDispatcher->onWindowInfosChanged(
5034 {{*windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Garfield Tan00f511d2019-06-12 16:55:40 -07005035
5036 // Inject an event with coordinate in the area of right window, with mouse cursor in the area of
5037 // left window. This event should be dispatched to the left window.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08005038 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005039 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005040 ui::LogicalDisplayId::DEFAULT, {610, 400}, {599, 400}));
5041 windowLeft->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan00f511d2019-06-12 16:55:40 -07005042 windowRight->assertNoEvents();
5043}
5044
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005045TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsKeyStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005046 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005047 sp<FakeWindowHandle> window =
5048 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5049 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair47074b82020-08-14 11:54:47 -07005050 window->setFocusable(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005051
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005052 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07005053 setFocusedWindow(window);
5054
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01005055 window->consumeFocusEvent(true);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005056
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005057 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005058
5059 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005060 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005061
5062 // When device reset happens, that key stream should be terminated with FLAG_CANCELED
5063 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005064 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005065 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT, AKEY_EVENT_FLAG_CANCELED);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005066}
5067
5068TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
Chris Yea209fde2020-07-22 13:54:51 -07005069 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005070 sp<FakeWindowHandle> window =
5071 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5072 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005073
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005074 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005075
Prabir Pradhan678438e2023-04-13 19:32:51 +00005076 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005077 AINPUT_SOURCE_TOUCHSCREEN,
5078 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005079
5080 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005081 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005082
5083 // When device reset happens, that motion stream should be terminated with ACTION_CANCEL
5084 // on the app side.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005085 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08005086 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005087 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08005088}
5089
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005090TEST_F(InputDispatcherTest, NotifyDeviceResetCancelsHoveringStream) {
5091 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005092 sp<FakeWindowHandle> window =
5093 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5094 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005095
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005096 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0686f0c2023-05-02 11:56:15 -07005097
5098 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5099 .pointer(PointerBuilder(0, ToolType::STYLUS).x(10).y(10))
5100 .build());
5101
5102 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5103
5104 // When device reset happens, that hover stream should be terminated with ACTION_HOVER_EXIT
5105 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
5106 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
5107
5108 // After the device has been reset, a new hovering stream can be sent to the window
5109 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
5110 .pointer(PointerBuilder(0, ToolType::STYLUS).x(15).y(15))
5111 .build());
5112 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
5113}
5114
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005115TEST_F(InputDispatcherTest, InterceptKeyByPolicy) {
5116 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005117 sp<FakeWindowHandle> window =
5118 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5119 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005120 window->setFocusable(true);
5121
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005122 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005123 setFocusedWindow(window);
5124
5125 window->consumeFocusEvent(true);
5126
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005127 const NotifyKeyArgs keyArgs =
5128 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005129 const std::chrono::milliseconds interceptKeyTimeout = 50ms;
5130 const nsecs_t injectTime = keyArgs.eventTime;
5131 mFakePolicy->setInterceptKeyTimeout(interceptKeyTimeout);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005132 mDispatcher->notifyKey(keyArgs);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005133 // The dispatching time should be always greater than or equal to intercept key timeout.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005134 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005135 ASSERT_TRUE((systemTime(SYSTEM_TIME_MONOTONIC) - injectTime) >=
5136 std::chrono::nanoseconds(interceptKeyTimeout).count());
5137}
5138
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005139/**
5140 * Keys with ACTION_UP are delivered immediately, even if a long 'intercept key timeout' is set.
5141 */
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005142TEST_F(InputDispatcherTest, InterceptKeyIfKeyUp) {
5143 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005144 sp<FakeWindowHandle> window =
5145 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5146 ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005147 window->setFocusable(true);
5148
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005149 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005150 setFocusedWindow(window);
5151
5152 window->consumeFocusEvent(true);
5153
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005154 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
5155 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005156
5157 // Set a value that's significantly larger than the default consumption timeout. If the
5158 // implementation is correct, the actual value doesn't matter; it won't slow down the test.
5159 mFakePolicy->setInterceptKeyTimeout(600ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005160 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf54d2ab2023-06-09 13:23:53 -07005161 // Window should receive key event immediately when same key up.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005162 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2ee6d0b2022-03-03 20:19:38 +08005163}
5164
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005165/**
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005166 * Two windows. First is a regular window. Second does not overlap with the first, and has
5167 * WATCH_OUTSIDE_TOUCH.
5168 * Both windows are owned by the same UID.
5169 * Tap first window. Make sure that the second window receives ACTION_OUTSIDE with correct, non-zero
5170 * coordinates. The coordinates are not zeroed out because both windows are owned by the same UID.
5171 */
5172TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinates) {
5173 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005174 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5175 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005176 window->setFrame(Rect{0, 0, 100, 100});
5177
5178 sp<FakeWindowHandle> outsideWindow =
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07005179 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005180 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005181 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5182 outsideWindow->setWatchOutsideTouch(true);
5183 // outsideWindow must be above 'window' to receive ACTION_OUTSIDE events when 'window' is tapped
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005184 mDispatcher->onWindowInfosChanged({{*outsideWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005185
5186 // Tap on first window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005187 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005188 AINPUT_SOURCE_TOUCHSCREEN,
5189 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005190 window->consumeMotionDown();
5191 // The coordinates of the tap in 'outsideWindow' are relative to its top left corner.
5192 // Therefore, we should offset them by (100, 100) relative to the screen's top left corner.
5193 outsideWindow->consumeMotionEvent(
5194 AllOf(WithMotionAction(ACTION_OUTSIDE), WithCoords(-50, -50)));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005195
5196 // Ensure outsideWindow doesn't get any more events for the gesture.
5197 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005198 ui::LogicalDisplayId::DEFAULT, {PointF{51, 51}}));
Prabir Pradhan502a7252023-12-01 16:11:24 +00005199 window->consumeMotionMove();
5200 outsideWindow->assertNoEvents();
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005201}
5202
5203/**
Linnan Liccf6ce32024-04-11 20:32:13 +08005204 * Three windows:
5205 * - Left window
5206 * - Right window
5207 * - Outside window(watch for ACTION_OUTSIDE events)
5208 * The windows "left" and "outside" share the same owner, the window "right" has a different owner,
5209 * In order to allow the outside window can receive the ACTION_OUTSIDE events, the outside window is
5210 * positioned above the "left" and "right" windows, and it doesn't overlap with them.
5211 *
5212 * First, device A report a down event landed in the right window, the outside window can receive
5213 * an ACTION_OUTSIDE event that with zeroed coordinates, the device B report a down event landed
5214 * in the left window, the outside window can receive an ACTION_OUTSIDE event the with valid
5215 * coordinates, after these, device A and device B continue report MOVE event, the right and left
5216 * window can receive it, but outside window event can't receive it.
5217 */
5218TEST_F(InputDispatcherTest, ActionOutsideForOwnedWindowHasValidCoordinatesWhenMultiDevice) {
5219 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5220 sp<FakeWindowHandle> leftWindow =
5221 sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005222 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005223 leftWindow->setFrame(Rect{0, 0, 100, 100});
5224 leftWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5225
5226 sp<FakeWindowHandle> outsideWindow =
5227 sp<FakeWindowHandle>::make(application, mDispatcher, "Outside Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005228 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005229 outsideWindow->setFrame(Rect{100, 100, 200, 200});
5230 outsideWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
5231 outsideWindow->setWatchOutsideTouch(true);
5232
5233 std::shared_ptr<FakeApplicationHandle> anotherApplication =
5234 std::make_shared<FakeApplicationHandle>();
5235 sp<FakeWindowHandle> rightWindow =
5236 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Right Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005237 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08005238 rightWindow->setFrame(Rect{100, 0, 200, 100});
5239 rightWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
5240
5241 // OutsideWindow must be above left window and right window to receive ACTION_OUTSIDE events
5242 // when left window or right window is tapped
5243 mDispatcher->onWindowInfosChanged(
5244 {{*outsideWindow->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()},
5245 {},
5246 0,
5247 0});
5248
5249 const DeviceId deviceA = 9;
5250 const DeviceId deviceB = 3;
5251
5252 // Tap on right window use device A
5253 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5254 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5255 .deviceId(deviceA)
5256 .build());
5257 leftWindow->assertNoEvents();
5258 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5259 // Right window is belonged to another owner, so outsideWindow should receive ACTION_OUTSIDE
5260 // with zeroed coords.
5261 outsideWindow->consumeMotionEvent(
5262 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceA), WithCoords(0, 0)));
5263
5264 // Tap on left window use device B
5265 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5266 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5267 .deviceId(deviceB)
5268 .build());
5269 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5270 rightWindow->assertNoEvents();
5271 // Because new gesture down on the left window that has the same owner with outside Window, the
5272 // outside Window should receive the ACTION_OUTSIDE with coords.
5273 outsideWindow->consumeMotionEvent(
5274 AllOf(WithMotionAction(ACTION_OUTSIDE), WithDeviceId(deviceB), WithCoords(-50, -50)));
5275
5276 // Ensure that windows that can only accept outside do not receive remaining gestures
5277 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5278 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
5279 .deviceId(deviceA)
5280 .build());
5281 leftWindow->assertNoEvents();
5282 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA)));
5283
5284 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
5285 .pointer(PointerBuilder(0, ToolType::FINGER).x(51).y(51))
5286 .deviceId(deviceB)
5287 .build());
5288 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
5289 rightWindow->assertNoEvents();
5290 outsideWindow->assertNoEvents();
5291}
5292
5293/**
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005294 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
5295 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
5296 * ACTION_OUTSIDE event is sent per gesture.
5297 */
5298TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
5299 // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
5300 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005301 sp<FakeWindowHandle> window =
5302 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
5303 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005304 window->setWatchOutsideTouch(true);
5305 window->setFrame(Rect{0, 0, 100, 100});
5306 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005307 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005308 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005309 secondWindow->setFrame(Rect{100, 100, 200, 200});
5310 sp<FakeWindowHandle> thirdWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005311 sp<FakeWindowHandle>::make(application, mDispatcher, "Third Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005312 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005313 thirdWindow->setFrame(Rect{200, 200, 300, 300});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005314 mDispatcher->onWindowInfosChanged(
5315 {{*window->getInfo(), *secondWindow->getInfo(), *thirdWindow->getInfo()}, {}, 0, 0});
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005316
5317 // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005318 mDispatcher->notifyMotion(
5319 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5320 ui::LogicalDisplayId::DEFAULT, {PointF{-10, -10}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005321 window->assertNoEvents();
5322 secondWindow->assertNoEvents();
5323
5324 // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
5325 // Now, `window` should get ACTION_OUTSIDE.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005326 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005327 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005328 {PointF{-10, -10}, PointF{105, 105}}));
Siarhei Vishniakou487c49b2022-12-02 15:48:57 -08005329 const std::map<int32_t, PointF> expectedPointers{{0, PointF{-10, -10}}, {1, PointF{105, 105}}};
5330 window->consumeMotionEvent(
5331 AllOf(WithMotionAction(ACTION_OUTSIDE), WithPointers(expectedPointers)));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005332 secondWindow->consumeMotionDown();
5333 thirdWindow->assertNoEvents();
5334
5335 // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
5336 // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005337 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005338 generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5339 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00005340 {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}}));
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005341 window->assertNoEvents();
5342 secondWindow->consumeMotionMove();
5343 thirdWindow->consumeMotionDown();
5344}
5345
Prabir Pradhan814fe082022-07-22 20:22:18 +00005346TEST_F(InputDispatcherTest, OnWindowInfosChanged_RemoveAllWindowsOnDisplay) {
5347 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005348 sp<FakeWindowHandle> window =
5349 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5350 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005351 window->setFocusable(true);
5352
Patrick Williamsd828f302023-04-28 17:52:08 -05005353 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005354 setFocusedWindow(window);
5355
5356 window->consumeFocusEvent(true);
5357
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005358 const NotifyKeyArgs keyDown =
5359 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
5360 const NotifyKeyArgs keyUp =
5361 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00005362 mDispatcher->notifyKey(keyDown);
5363 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005364
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005365 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
5366 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005367
5368 // All windows are removed from the display. Ensure that we can no longer dispatch to it.
Patrick Williamsd828f302023-04-28 17:52:08 -05005369 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Prabir Pradhan814fe082022-07-22 20:22:18 +00005370
5371 window->consumeFocusEvent(false);
5372
Prabir Pradhan678438e2023-04-13 19:32:51 +00005373 mDispatcher->notifyKey(keyDown);
5374 mDispatcher->notifyKey(keyUp);
Prabir Pradhan814fe082022-07-22 20:22:18 +00005375 window->assertNoEvents();
5376}
5377
Arthur Hung96483742022-11-15 03:30:48 +00005378TEST_F(InputDispatcherTest, NonSplitTouchableWindowReceivesMultiTouch) {
5379 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005380 sp<FakeWindowHandle> window =
5381 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
5382 ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005383 // Ensure window is non-split and have some transform.
5384 window->setPreventSplitting(true);
5385 window->setWindowOffset(20, 40);
Patrick Williamsd828f302023-04-28 17:52:08 -05005386 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Arthur Hung96483742022-11-15 03:30:48 +00005387
5388 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005389 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5390 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung96483742022-11-15 03:30:48 +00005391 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005392 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung96483742022-11-15 03:30:48 +00005393
5394 const MotionEvent secondFingerDownEvent =
5395 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005396 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung96483742022-11-15 03:30:48 +00005397 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005398 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5399 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(-30).y(-50))
Arthur Hung96483742022-11-15 03:30:48 +00005400 .build();
5401 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005402 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung96483742022-11-15 03:30:48 +00005403 InputEventInjectionSync::WAIT_FOR_RESULT))
5404 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5405
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005406 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
5407 ASSERT_NE(nullptr, event);
5408 EXPECT_EQ(POINTER_1_DOWN, event->getAction());
5409 EXPECT_EQ(70, event->getX(0)); // 50 + 20
5410 EXPECT_EQ(90, event->getY(0)); // 50 + 40
5411 EXPECT_EQ(-10, event->getX(1)); // -30 + 20
5412 EXPECT_EQ(-10, event->getY(1)); // -50 + 40
Arthur Hung96483742022-11-15 03:30:48 +00005413}
5414
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005415/**
5416 * Two windows: a splittable and a non-splittable.
5417 * The non-splittable window shouldn't receive any "incomplete" gestures.
5418 * Send the first pointer to the splittable window, and then touch the non-splittable window.
5419 * The second pointer should be dropped because the initial window is splittable, so it won't get
5420 * any pointers outside of it, and the second window is non-splittable, so it shouldn't get any
5421 * "incomplete" gestures.
5422 */
5423TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
5424 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5425 sp<FakeWindowHandle> leftWindow =
5426 sp<FakeWindowHandle>::make(application, mDispatcher, "Left splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005427 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005428 leftWindow->setPreventSplitting(false);
5429 leftWindow->setFrame(Rect(0, 0, 100, 100));
5430 sp<FakeWindowHandle> rightWindow =
5431 sp<FakeWindowHandle>::make(application, mDispatcher, "Right non-splittable Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005432 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou25537f82023-07-18 14:35:47 -07005433 rightWindow->setPreventSplitting(true);
5434 rightWindow->setFrame(Rect(100, 100, 200, 200));
5435 mDispatcher->onWindowInfosChanged(
5436 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5437
5438 // Touch down on left, splittable window
5439 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5440 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5441 .build());
5442 leftWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5443
5444 mDispatcher->notifyMotion(
5445 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5446 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
5447 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
5448 .build());
5449 leftWindow->assertNoEvents();
5450 rightWindow->assertNoEvents();
5451}
5452
Siarhei Vishniakou27fc9f12024-07-13 23:59:47 -07005453/**
5454 * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a
5455 * down event to the right window. Device B sends a down event to the left window, and then a
5456 * POINTER_DOWN event to the right window. However, since the left window prevents splitting, the
5457 * POINTER_DOWN event should only go to the left window, and not to the right window.
5458 * This test attempts to reproduce a crash.
5459 */
5460TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) {
5461 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5462 sp<FakeWindowHandle> leftWindow =
5463 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)",
5464 ui::LogicalDisplayId::DEFAULT);
5465 leftWindow->setFrame(Rect(0, 0, 100, 100));
5466 leftWindow->setPreventSplitting(true);
5467
5468 sp<FakeWindowHandle> rightWindow =
5469 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
5470 ui::LogicalDisplayId::DEFAULT);
5471 rightWindow->setFrame(Rect(100, 0, 200, 100));
5472
5473 mDispatcher->onWindowInfosChanged(
5474 {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5475
5476 const DeviceId deviceA = 9;
5477 const DeviceId deviceB = 3;
5478 // Touch the right window with device A
5479 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5480 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5481 .deviceId(deviceA)
5482 .build());
5483 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5484 // Touch the left window with device B
5485 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5486 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5487 .deviceId(deviceB)
5488 .build());
5489 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5490 // Send a second pointer from device B to the right window. It shouldn't go to the right window
5491 // because the left window prevents splitting.
5492 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5493 .deviceId(deviceB)
5494 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5495 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
5496 .build());
5497 leftWindow->consumeMotionPointerDown(1, WithDeviceId(deviceB));
5498
5499 // Finish the gesture for both devices
5500 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5501 .deviceId(deviceB)
5502 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5503 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
5504 .build());
5505 leftWindow->consumeMotionPointerUp(1, WithDeviceId(deviceB));
5506 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5507 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5508 .deviceId(deviceB)
5509 .build());
5510 leftWindow->consumeMotionEvent(
5511 AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithPointerId(0, 0)));
5512 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5513 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5514 .deviceId(deviceA)
5515 .build());
5516 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA)));
5517}
5518
Harry Cuttsb166c002023-05-09 13:06:05 +00005519TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
5520 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005521 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5522 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005523 window->setFrame(Rect(0, 0, 400, 400));
5524 sp<FakeWindowHandle> trustedOverlay =
5525 sp<FakeWindowHandle>::make(application, mDispatcher, "Trusted Overlay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005526 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005527 trustedOverlay->setSpy(true);
5528 trustedOverlay->setTrustedOverlay(true);
5529
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005530 mDispatcher->onWindowInfosChanged({{*trustedOverlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005531
5532 // Start a three-finger touchpad swipe
5533 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5534 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5535 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5536 .build());
5537 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5538 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5539 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5540 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5541 .build());
5542 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5543 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5544 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5545 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5546 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5547 .build());
5548
5549 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5550 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5551 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_DOWN));
5552
5553 // Move the swipe a bit
5554 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5555 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5556 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5557 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5558 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5559 .build());
5560
5561 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
5562
5563 // End the swipe
5564 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5565 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5566 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5567 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5568 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5569 .build());
5570 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5571 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5572 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5573 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5574 .build());
5575 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5576 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5577 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5578 .build());
5579
5580 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_2_UP));
5581 trustedOverlay->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5582 trustedOverlay->consumeMotionEvent(WithMotionAction(ACTION_UP));
5583
5584 window->assertNoEvents();
5585}
5586
5587TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeNotSentToSingleWindow) {
5588 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005589 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5590 ui::LogicalDisplayId::DEFAULT);
Harry Cuttsb166c002023-05-09 13:06:05 +00005591 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07005592 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cuttsb166c002023-05-09 13:06:05 +00005593
5594 // Start a three-finger touchpad swipe
5595 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
5596 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5597 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5598 .build());
5599 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_MOUSE)
5600 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5601 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5602 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5603 .build());
5604 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_DOWN, AINPUT_SOURCE_MOUSE)
5605 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(100))
5606 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(100))
5607 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(100))
5608 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5609 .build());
5610
5611 // Move the swipe a bit
5612 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE)
5613 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5614 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5615 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5616 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5617 .build());
5618
5619 // End the swipe
5620 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_2_UP, AINPUT_SOURCE_MOUSE)
5621 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5622 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5623 .pointer(PointerBuilder(2, ToolType::FINGER).x(300).y(105))
5624 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5625 .build());
5626 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_MOUSE)
5627 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5628 .pointer(PointerBuilder(1, ToolType::FINGER).x(250).y(105))
5629 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5630 .build());
5631 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
5632 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(105))
5633 .classification(MotionClassification::MULTI_FINGER_SWIPE)
5634 .build());
5635
5636 window->assertNoEvents();
5637}
5638
Prabir Pradhanb60b1dc2022-03-15 14:02:35 +00005639/**
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005640 * Send a two-pointer gesture to a single window. The window's orientation changes in response to
5641 * the first pointer.
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005642 * Ensure that the second pointer and the subsequent gesture is correctly delivered to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005643 */
5644TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
5645 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005646 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
5647 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005648 window->setFrame(Rect(0, 0, 400, 400));
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005649 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005650
5651 const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
5652 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5653 .downTime(baseTime + 10)
5654 .eventTime(baseTime + 10)
5655 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5656 .build());
5657
5658 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
5659
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005660 // Change the transform so that the orientation is now different from original.
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005661 window->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005662
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005663 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005664
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005665 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5666 .downTime(baseTime + 10)
5667 .eventTime(baseTime + 30)
5668 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5669 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5670 .build());
5671
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005672 window->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
5673
5674 // Finish the gesture and start a new one. Ensure all events are sent to the window.
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005675 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5676 .downTime(baseTime + 10)
5677 .eventTime(baseTime + 40)
5678 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5679 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
5680 .build());
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005681
5682 window->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
5683
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005684 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5685 .downTime(baseTime + 10)
5686 .eventTime(baseTime + 50)
5687 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
5688 .build());
5689
Prabir Pradhan69d00bf2023-06-23 19:55:18 +00005690 window->consumeMotionEvent(WithMotionAction(ACTION_UP));
5691
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005692 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5693 .downTime(baseTime + 60)
5694 .eventTime(baseTime + 60)
5695 .pointer(PointerBuilder(0, ToolType::FINGER).x(40).y(40))
5696 .build());
5697
Siarhei Vishniakou700424c2023-07-18 17:18:42 -07005698 window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07005699}
5700
5701/**
Hu Guo771a7692023-09-17 20:51:08 +08005702 * When there are multiple screens, such as screen projection to TV or screen recording, if the
5703 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
5704 * its coordinates should be converted by the transform of the windows of target screen.
5705 */
5706TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
5707 // This case will create a window and a spy window on the default display and mirror
5708 // window on the second display. cancel event is sent through spy window pilferPointers
5709 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5710
5711 sp<FakeWindowHandle> spyWindowDefaultDisplay =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005712 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
5713 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005714 spyWindowDefaultDisplay->setTrustedOverlay(true);
5715 spyWindowDefaultDisplay->setSpy(true);
5716
5717 sp<FakeWindowHandle> windowDefaultDisplay =
5718 sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005719 ui::LogicalDisplayId::DEFAULT);
Hu Guo771a7692023-09-17 20:51:08 +08005720 windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);
5721
5722 sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
5723 windowSecondDisplay->setWindowTransform(2, 0, 0, 2);
5724
5725 // Add the windows to the dispatcher
5726 mDispatcher->onWindowInfosChanged(
5727 {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
5728 *windowSecondDisplay->getInfo()},
5729 {},
5730 0,
5731 0});
5732
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005733 // Send down to ui::LogicalDisplayId::DEFAULT
Hu Guo771a7692023-09-17 20:51:08 +08005734 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005735 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
5736 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Hu Guo771a7692023-09-17 20:51:08 +08005737 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
5738
5739 spyWindowDefaultDisplay->consumeMotionDown();
5740 windowDefaultDisplay->consumeMotionDown();
5741
5742 EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));
5743
5744 // windowDefaultDisplay gets cancel
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005745 std::unique_ptr<MotionEvent> event = windowDefaultDisplay->consumeMotionEvent();
5746 ASSERT_NE(nullptr, event);
5747 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());
Hu Guo771a7692023-09-17 20:51:08 +08005748
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005749 // The cancel event is sent to windowDefaultDisplay of the ui::LogicalDisplayId::DEFAULT
5750 // display, so the coordinates of the cancel are converted by windowDefaultDisplay's transform,
5751 // the x and y coordinates are both 100, otherwise if the cancel event is sent to
5752 // windowSecondDisplay of SECOND_DISPLAY_ID, the x and y coordinates are 200
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005753 EXPECT_EQ(100, event->getX(0));
5754 EXPECT_EQ(100, event->getY(0));
Hu Guo771a7692023-09-17 20:51:08 +08005755}
5756
5757/**
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005758 * Ensure the correct coordinate spaces are used by InputDispatcher.
5759 *
5760 * InputDispatcher works in the display space, so its coordinate system is relative to the display
5761 * panel. Windows get events in the window space, and get raw coordinates in the logical display
5762 * space.
5763 */
5764class InputDispatcherDisplayProjectionTest : public InputDispatcherTest {
5765public:
5766 void SetUp() override {
5767 InputDispatcherTest::SetUp();
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005768 removeAllWindowsAndDisplays();
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005769 }
5770
Linnan Li13bf76a2024-05-05 19:18:02 +08005771 void addDisplayInfo(ui::LogicalDisplayId displayId, const ui::Transform& transform) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005772 gui::DisplayInfo info;
5773 info.displayId = displayId;
5774 info.transform = transform;
5775 mDisplayInfos.push_back(std::move(info));
Patrick Williamsd828f302023-04-28 17:52:08 -05005776 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005777 }
5778
5779 void addWindow(const sp<WindowInfoHandle>& windowHandle) {
5780 mWindowInfos.push_back(*windowHandle->getInfo());
Patrick Williamsd828f302023-04-28 17:52:08 -05005781 mDispatcher->onWindowInfosChanged({mWindowInfos, mDisplayInfos, 0, 0});
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005782 }
5783
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005784 void removeAllWindowsAndDisplays() {
5785 mDisplayInfos.clear();
5786 mWindowInfos.clear();
5787 }
5788
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005789 // Set up a test scenario where the display has a scaled projection and there are two windows
5790 // on the display.
5791 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupScaledDisplayScenario() {
5792 // The display has a projection that has a scale factor of 2 and 4 in the x and y directions
5793 // respectively.
5794 ui::Transform displayTransform;
5795 displayTransform.set(2, 0, 0, 4);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005796 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005797
5798 std::shared_ptr<FakeApplicationHandle> application =
5799 std::make_shared<FakeApplicationHandle>();
5800
5801 // Add two windows to the display. Their frames are represented in the display space.
5802 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005803 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005804 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005805 firstWindow->setFrame(Rect(0, 0, 100, 200), displayTransform);
5806 addWindow(firstWindow);
5807
5808 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07005809 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005810 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005811 secondWindow->setFrame(Rect(100, 200, 200, 400), displayTransform);
5812 addWindow(secondWindow);
5813 return {std::move(firstWindow), std::move(secondWindow)};
5814 }
5815
5816private:
5817 std::vector<gui::DisplayInfo> mDisplayInfos;
5818 std::vector<gui::WindowInfo> mWindowInfos;
5819};
5820
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005821TEST_F(InputDispatcherDisplayProjectionTest, HitTestCoordinateSpaceConsistency) {
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005822 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5823 // Send down to the first window. The point is represented in the display space. The point is
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00005824 // selected so that if the hit test was performed with the point and the bounds being in
5825 // different coordinate spaces, the event would end up in the incorrect window.
Prabir Pradhan678438e2023-04-13 19:32:51 +00005826 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005827 AINPUT_SOURCE_TOUCHSCREEN,
5828 ui::LogicalDisplayId::DEFAULT, {PointF{75, 55}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005829
5830 firstWindow->consumeMotionDown();
5831 secondWindow->assertNoEvents();
5832}
5833
5834// Ensure that when a MotionEvent is injected through the InputDispatcher::injectInputEvent() API,
5835// the event should be treated as being in the logical display space.
5836TEST_F(InputDispatcherDisplayProjectionTest, InjectionInLogicalDisplaySpace) {
5837 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5838 // Send down to the first window. The point is represented in the logical display space. The
5839 // point is selected so that if the hit test was done in logical display space, then it would
5840 // end up in the incorrect window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005841 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005842 PointF{75 * 2, 55 * 4});
5843
5844 firstWindow->consumeMotionDown();
5845 secondWindow->assertNoEvents();
5846}
5847
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005848// Ensure that when a MotionEvent that has a custom transform is injected, the post-transformed
5849// event should be treated as being in the logical display space.
5850TEST_F(InputDispatcherDisplayProjectionTest, InjectionWithTransformInLogicalDisplaySpace) {
5851 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5852
5853 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5854 ui::Transform injectedEventTransform;
5855 injectedEventTransform.set(matrix);
5856 const vec2 expectedPoint{75, 55}; // The injected point in the logical display space.
5857 const vec2 untransformedPoint = injectedEventTransform.inverse().transform(expectedPoint);
5858
5859 MotionEvent event = MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005860 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005861 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07005862 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER)
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005863 .x(untransformedPoint.x)
5864 .y(untransformedPoint.y))
5865 .build();
5866 event.transform(matrix);
5867
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07005868 injectMotionEvent(*mDispatcher, event, INJECT_EVENT_TIMEOUT,
Prabir Pradhandaa2f142021-12-10 09:30:08 +00005869 InputEventInjectionSync::WAIT_FOR_RESULT);
5870
5871 firstWindow->consumeMotionDown();
5872 secondWindow->assertNoEvents();
5873}
5874
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005875TEST_F(InputDispatcherDisplayProjectionTest, WindowGetsEventsInCorrectCoordinateSpace) {
5876 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5877
5878 // Send down to the second window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005879 mDispatcher->notifyMotion(
5880 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
5881 ui::LogicalDisplayId::DEFAULT, {PointF{150, 220}}));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005882
5883 firstWindow->assertNoEvents();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005884 std::unique_ptr<MotionEvent> event = secondWindow->consumeMotionEvent();
5885 ASSERT_NE(nullptr, event);
5886 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, event->getAction());
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005887
5888 // Ensure that the events from the "getRaw" API are in logical display coordinates.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005889 EXPECT_EQ(300, event->getRawX(0));
5890 EXPECT_EQ(880, event->getRawY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005891
5892 // Ensure that the x and y values are in the window's coordinate space.
5893 // The left-top of the second window is at (100, 200) in display space, which is (200, 800) in
5894 // the logical display space. This will be the origin of the window space.
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08005895 EXPECT_EQ(100, event->getX(0));
5896 EXPECT_EQ(80, event->getY(0));
Prabir Pradhanc44ce4d2021-10-05 05:26:29 -07005897}
5898
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005899TEST_F(InputDispatcherDisplayProjectionTest, CancelMotionWithCorrectCoordinates) {
5900 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5901 // The monitor will always receive events in the logical display's coordinate space, because
5902 // it does not have a window.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005903 FakeMonitorReceiver monitor{*mDispatcher, "Monitor", ui::LogicalDisplayId::DEFAULT};
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005904
5905 // Send down to the first window.
5906 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005907 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005908 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5909 monitor.consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5910
5911 // Second pointer goes down on second window.
5912 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005913 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan112b1ad2023-09-21 09:53:53 +00005914 {PointF{50, 100}, PointF{150, 220}}));
5915 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80)));
5916 const std::map<int32_t, PointF> expectedMonitorPointers{{0, PointF{100, 400}},
5917 {1, PointF{300, 880}}};
5918 monitor.consumeMotionEvent(
5919 AllOf(WithMotionAction(POINTER_1_DOWN), WithPointers(expectedMonitorPointers)));
5920
5921 mDispatcher->cancelCurrentTouch();
5922
5923 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5924 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 80)));
5925 monitor.consumeMotionEvent(
5926 AllOf(WithMotionAction(ACTION_CANCEL), WithPointers(expectedMonitorPointers)));
5927}
5928
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005929TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeDownWithCorrectCoordinates) {
5930 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5931
5932 // Send down to the first window.
5933 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005934 ui::LogicalDisplayId::DEFAULT, {PointF{50, 100}}));
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005935 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 400)));
5936
5937 // The pointer is transferred to the second window, and the second window receives it in the
5938 // correct coordinate space.
Prabir Pradhan367f3432024-02-13 23:05:58 +00005939 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Prabir Pradhan1c29a092023-09-21 10:29:29 +00005940 firstWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithCoords(100, 400)));
5941 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithCoords(-100, -400)));
5942}
5943
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005944TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverEnterExitWithCorrectCoordinates) {
5945 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5946
5947 // Send hover move to the second window, and ensure it shows up as hover enter.
5948 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005949 ui::LogicalDisplayId::DEFAULT,
5950 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005951 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5952 WithCoords(100, 80), WithRawCoords(300, 880)));
5953
5954 // Touch down at the same location and ensure a hover exit is synthesized.
5955 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005956 ui::LogicalDisplayId::DEFAULT,
5957 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00005958 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5959 WithRawCoords(300, 880)));
5960 secondWindow->consumeMotionEvent(
5961 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5962 secondWindow->assertNoEvents();
5963 firstWindow->assertNoEvents();
5964}
5965
Prabir Pradhan453ae732023-10-13 14:30:14 +00005966// Same as above, but while the window is being mirrored.
5967TEST_F(InputDispatcherDisplayProjectionTest,
5968 SynthesizeHoverEnterExitWithCorrectCoordinatesWhenMirrored) {
5969 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
5970
5971 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
5972 ui::Transform secondDisplayTransform;
5973 secondDisplayTransform.set(matrix);
5974 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
5975
5976 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
5977 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
5978 addWindow(secondWindowClone);
5979
5980 // Send hover move to the second window, and ensure it shows up as hover enter.
5981 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005982 ui::LogicalDisplayId::DEFAULT,
5983 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00005984 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
5985 WithCoords(100, 80), WithRawCoords(300, 880)));
5986
5987 // Touch down at the same location and ensure a hover exit is synthesized for the correct
5988 // display.
5989 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07005990 ui::LogicalDisplayId::DEFAULT,
5991 {PointF{150, 220}}));
Prabir Pradhan453ae732023-10-13 14:30:14 +00005992 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
5993 WithRawCoords(300, 880)));
5994 secondWindow->consumeMotionEvent(
5995 AllOf(WithMotionAction(ACTION_DOWN), WithCoords(100, 80), WithRawCoords(300, 880)));
5996 secondWindow->assertNoEvents();
5997 firstWindow->assertNoEvents();
5998}
5999
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006000TEST_F(InputDispatcherDisplayProjectionTest, SynthesizeHoverCancelationWithCorrectCoordinates) {
6001 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6002
6003 // Send hover enter to second window
6004 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006005 ui::LogicalDisplayId::DEFAULT,
6006 {PointF{150, 220}}));
Prabir Pradhan0dfcac72023-10-05 20:04:21 +00006007 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6008 WithCoords(100, 80), WithRawCoords(300, 880)));
6009
6010 mDispatcher->cancelCurrentTouch();
6011
6012 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6013 WithRawCoords(300, 880)));
6014 secondWindow->assertNoEvents();
6015 firstWindow->assertNoEvents();
6016}
6017
Prabir Pradhan453ae732023-10-13 14:30:14 +00006018// Same as above, but while the window is being mirrored.
Prabir Pradhan16463382023-10-12 23:03:19 +00006019TEST_F(InputDispatcherDisplayProjectionTest,
6020 SynthesizeHoverCancelationWithCorrectCoordinatesWhenMirrored) {
6021 auto [firstWindow, secondWindow] = setupScaledDisplayScenario();
6022
6023 const std::array<float, 9> matrix = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0.0, 0.0, 1.0};
6024 ui::Transform secondDisplayTransform;
6025 secondDisplayTransform.set(matrix);
6026 addDisplayInfo(SECOND_DISPLAY_ID, secondDisplayTransform);
6027
6028 sp<FakeWindowHandle> secondWindowClone = secondWindow->clone(SECOND_DISPLAY_ID);
6029 secondWindowClone->setWindowTransform(1.1, 2.2, 3.3, 4.4);
6030 addWindow(secondWindowClone);
6031
6032 // Send hover enter to second window
6033 mDispatcher->notifyMotion(generateMotionArgs(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006034 ui::LogicalDisplayId::DEFAULT,
6035 {PointF{150, 220}}));
Prabir Pradhan16463382023-10-12 23:03:19 +00006036 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
6037 WithCoords(100, 80), WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006038 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00006039
6040 mDispatcher->cancelCurrentTouch();
6041
6042 // Ensure the cancelation happens with the correct displayId and the correct coordinates.
6043 secondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithCoords(100, 80),
6044 WithRawCoords(300, 880),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006045 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan16463382023-10-12 23:03:19 +00006046 secondWindow->assertNoEvents();
6047 firstWindow->assertNoEvents();
6048}
6049
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006050/** Ensure consistent behavior of InputDispatcher in all orientations. */
6051class InputDispatcherDisplayOrientationFixture
6052 : public InputDispatcherDisplayProjectionTest,
6053 public ::testing::WithParamInterface<ui::Rotation> {};
6054
6055// This test verifies the touchable region of a window for all rotations of the display by tapping
6056// in different locations on the display, specifically points close to the four corners of a
6057// window.
6058TEST_P(InputDispatcherDisplayOrientationFixture, HitTestInDifferentOrientations) {
6059 constexpr static int32_t displayWidth = 400;
6060 constexpr static int32_t displayHeight = 800;
6061
6062 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6063
6064 const auto rotation = GetParam();
6065
6066 // Set up the display with the specified rotation.
6067 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6068 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6069 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6070 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6071 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006072 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006073
6074 // Create a window with its bounds determined in the logical display.
6075 const Rect frameInLogicalDisplay(100, 100, 200, 300);
6076 const Rect frameInDisplay = displayTransform.inverse().transform(frameInLogicalDisplay);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006077 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6078 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006079 window->setFrame(frameInDisplay, displayTransform);
6080 addWindow(window);
6081
6082 // The following points in logical display space should be inside the window.
6083 static const std::array<vec2, 4> insidePoints{
6084 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6085 for (const auto pointInsideWindow : insidePoints) {
6086 const vec2 p = displayTransform.inverse().transform(pointInsideWindow);
6087 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006088 mDispatcher->notifyMotion(
6089 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6090 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006091 window->consumeMotionDown();
6092
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006093 mDispatcher->notifyMotion(
6094 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6095 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006096 window->consumeMotionUp();
6097 }
6098
6099 // The following points in logical display space should be outside the window.
6100 static const std::array<vec2, 5> outsidePoints{
6101 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6102 for (const auto pointOutsideWindow : outsidePoints) {
6103 const vec2 p = displayTransform.inverse().transform(pointOutsideWindow);
6104 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006105 mDispatcher->notifyMotion(
6106 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6107 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006108
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006109 mDispatcher->notifyMotion(
6110 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6111 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006112 }
6113 window->assertNoEvents();
6114}
6115
Linnan Li5e5645e2024-03-05 14:43:05 +00006116// This test verifies the occlusion detection for all rotations of the display by tapping
6117// in different locations on the display, specifically points close to the four corners of a
6118// window.
6119TEST_P(InputDispatcherDisplayOrientationFixture, BlockUntrustClickInDifferentOrientations) {
6120 constexpr static int32_t displayWidth = 400;
6121 constexpr static int32_t displayHeight = 800;
6122
6123 std::shared_ptr<FakeApplicationHandle> untrustedWindowApplication =
6124 std::make_shared<FakeApplicationHandle>();
6125 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6126
6127 const auto rotation = GetParam();
6128
6129 // Set up the display with the specified rotation.
6130 const bool isRotated = rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270;
6131 const int32_t logicalDisplayWidth = isRotated ? displayHeight : displayWidth;
6132 const int32_t logicalDisplayHeight = isRotated ? displayWidth : displayHeight;
6133 const ui::Transform displayTransform(ui::Transform::toRotationFlags(rotation),
6134 logicalDisplayWidth, logicalDisplayHeight);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006135 addDisplayInfo(ui::LogicalDisplayId::DEFAULT, displayTransform);
Linnan Li5e5645e2024-03-05 14:43:05 +00006136
6137 // Create a window that not trusted.
6138 const Rect untrustedWindowFrameInLogicalDisplay(100, 100, 200, 300);
6139
6140 const Rect untrustedWindowFrameInDisplay =
6141 displayTransform.inverse().transform(untrustedWindowFrameInLogicalDisplay);
6142
6143 sp<FakeWindowHandle> untrustedWindow =
6144 sp<FakeWindowHandle>::make(untrustedWindowApplication, mDispatcher, "UntrustedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006145 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006146 untrustedWindow->setFrame(untrustedWindowFrameInDisplay, displayTransform);
6147 untrustedWindow->setTrustedOverlay(false);
6148 untrustedWindow->setTouchOcclusionMode(TouchOcclusionMode::BLOCK_UNTRUSTED);
6149 untrustedWindow->setTouchable(false);
6150 untrustedWindow->setAlpha(1.0f);
6151 untrustedWindow->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
6152 addWindow(untrustedWindow);
6153
6154 // Create a simple app window below the untrusted window.
6155 const Rect simpleAppWindowFrameInLogicalDisplay(0, 0, 300, 600);
6156 const Rect simpleAppWindowFrameInDisplay =
6157 displayTransform.inverse().transform(simpleAppWindowFrameInLogicalDisplay);
6158
6159 sp<FakeWindowHandle> simpleAppWindow =
6160 sp<FakeWindowHandle>::make(application, mDispatcher, "SimpleAppWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006161 ui::LogicalDisplayId::DEFAULT);
Linnan Li5e5645e2024-03-05 14:43:05 +00006162 simpleAppWindow->setFrame(simpleAppWindowFrameInDisplay, displayTransform);
6163 simpleAppWindow->setOwnerInfo(gui::Pid{2}, gui::Uid{202});
6164 addWindow(simpleAppWindow);
6165
6166 // The following points in logical display space should be inside the untrusted window, so
6167 // the simple window could not receive events that coordinate is these point.
6168 static const std::array<vec2, 4> untrustedPoints{
6169 {{100, 100}, {199.99, 100}, {100, 299.99}, {199.99, 299.99}}};
6170
6171 for (const auto untrustedPoint : untrustedPoints) {
6172 const vec2 p = displayTransform.inverse().transform(untrustedPoint);
6173 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006174 mDispatcher->notifyMotion(
6175 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6176 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6177 mDispatcher->notifyMotion(
6178 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6179 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
Linnan Li5e5645e2024-03-05 14:43:05 +00006180 }
6181 untrustedWindow->assertNoEvents();
6182 simpleAppWindow->assertNoEvents();
6183 // The following points in logical display space should be outside the untrusted window, so
6184 // the simple window should receive events that coordinate is these point.
6185 static const std::array<vec2, 5> trustedPoints{
6186 {{200, 100}, {100, 300}, {200, 300}, {100, 99.99}, {99.99, 100}}};
6187 for (const auto trustedPoint : trustedPoints) {
6188 const vec2 p = displayTransform.inverse().transform(trustedPoint);
6189 const PointF pointInDisplaySpace{p.x, p.y};
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006190 mDispatcher->notifyMotion(
6191 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
6192 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6193 simpleAppWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006194 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006195 mDispatcher->notifyMotion(
6196 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
6197 ui::LogicalDisplayId::DEFAULT, {pointInDisplaySpace}));
6198 simpleAppWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li5e5645e2024-03-05 14:43:05 +00006199 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
6200 }
6201 untrustedWindow->assertNoEvents();
6202}
6203
Prabir Pradhan33e3baa2022-12-06 20:30:22 +00006204// Run the precision tests for all rotations.
6205INSTANTIATE_TEST_SUITE_P(InputDispatcherDisplayOrientationTests,
6206 InputDispatcherDisplayOrientationFixture,
6207 ::testing::Values(ui::ROTATION_0, ui::ROTATION_90, ui::ROTATION_180,
6208 ui::ROTATION_270),
6209 [](const testing::TestParamInfo<ui::Rotation>& testParamInfo) {
6210 return ftl::enum_string(testParamInfo.param);
6211 });
6212
Siarhei Vishniakou18050092021-09-01 13:32:49 -07006213using TransferFunction = std::function<bool(const std::unique_ptr<InputDispatcher>& dispatcher,
6214 sp<IBinder>, sp<IBinder>)>;
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006215
6216class TransferTouchFixture : public InputDispatcherTest,
6217 public ::testing::WithParamInterface<TransferFunction> {};
6218
6219TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
Chris Yea209fde2020-07-22 13:54:51 -07006220 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006221
6222 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006223 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006224 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006225 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006226 firstWindow->setDupTouchToWallpaper(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006227 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006228 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006229 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006230 sp<FakeWindowHandle> wallpaper =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006231 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper",
6232 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006233 wallpaper->setIsWallpaper(true);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006234 // Add the windows to the dispatcher, and ensure the first window is focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006235 mDispatcher->onWindowInfosChanged(
6236 {{*firstWindow->getInfo(), *secondWindow->getInfo(), *wallpaper->getInfo()}, {}, 0, 0});
Prabir Pradhan65455c72024-02-13 21:46:41 +00006237 setFocusedWindow(firstWindow);
6238 firstWindow->consumeFocusEvent(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006239
6240 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006241 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006242 AINPUT_SOURCE_TOUCHSCREEN,
6243 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006244
Svet Ganov5d3bc372020-01-26 23:11:07 -08006245 // Only the first window should get the down event
6246 firstWindow->consumeMotionDown();
6247 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006248 wallpaper->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006249 // Dispatcher reports pointer down outside focus for the wallpaper
6250 mFakePolicy->assertOnPointerDownEquals(wallpaper->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006251
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006252 // Transfer touch to the second window
6253 TransferFunction f = GetParam();
6254 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6255 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006256 // The first window gets cancel and the second gets down
6257 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006258 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6259 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6260 wallpaper->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006261 // There should not be any changes to the focused window when transferring touch
6262 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertOnPointerDownWasNotCalled());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006263
6264 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006265 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006266 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan65455c72024-02-13 21:46:41 +00006267 // The first window gets no events and the second gets up
Svet Ganov5d3bc372020-01-26 23:11:07 -08006268 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006269 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6270 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006271 wallpaper->assertNoEvents();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006272}
6273
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006274/**
Prabir Pradhan367f3432024-02-13 23:05:58 +00006275 * When 'transferTouchGesture' API is invoked, dispatcher needs to find the "best" window to take
6276 * touch from. When we have spy windows, there are several windows to choose from: either spy, or
6277 * the 'real' (non-spy) window. Always prefer the 'real' window because that's what would be most
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006278 * natural to the user.
6279 * In this test, we are sending a pointer to both spy window and first window. We then try to
6280 * transfer touch to the second window. The dispatcher should identify the first window as the
6281 * one that should lose the gesture, and therefore the action should be to move the gesture from
6282 * the first window to the second.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006283 * The main goal here is to test the behaviour of 'transferTouchGesture' API, but it's still valid
6284 * to test the other API, as well.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006285 */
6286TEST_P(TransferTouchFixture, TransferTouch_MultipleWindowsWithSpy) {
6287 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6288
6289 // Create a couple of windows + a spy window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006290 sp<FakeWindowHandle> spyWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy",
6291 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006292 spyWindow->setTrustedOverlay(true);
6293 spyWindow->setSpy(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006294 sp<FakeWindowHandle> firstWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "First",
6295 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006296 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006297 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
6298 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006299
6300 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006301 mDispatcher->onWindowInfosChanged(
6302 {{*spyWindow->getInfo(), *firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006303
6304 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006305 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006306 AINPUT_SOURCE_TOUCHSCREEN,
6307 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006308 // Only the first window and spy should get the down event
6309 spyWindow->consumeMotionDown();
6310 firstWindow->consumeMotionDown();
6311
6312 // Transfer touch to the second window. Non-spy window should be preferred over the spy window
Prabir Pradhan367f3432024-02-13 23:05:58 +00006313 // if f === 'transferTouchGesture'.
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006314 TransferFunction f = GetParam();
6315 const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6316 ASSERT_TRUE(success);
6317 // The first window gets cancel and the second gets down
6318 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006319 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6320 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006321
6322 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006323 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006324 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006325 // The first window gets no events and the second+spy get up
6326 firstWindow->assertNoEvents();
6327 spyWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006328 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6329 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakou7ae7afd2022-03-31 15:26:13 -07006330}
6331
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006332TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006333 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006334
6335 PointF touchPoint = {10, 10};
6336
6337 // Create a couple of windows
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006338 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006339 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006340 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006341 firstWindow->setPreventSplitting(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006342 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006343 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006344 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08006345 secondWindow->setPreventSplitting(true);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006346
6347 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006348 mDispatcher->onWindowInfosChanged(
6349 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006350
6351 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006352 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006353 AINPUT_SOURCE_TOUCHSCREEN,
6354 ui::LogicalDisplayId::DEFAULT, {touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006355 // Only the first window should get the down event
6356 firstWindow->consumeMotionDown();
6357 secondWindow->assertNoEvents();
6358
6359 // Send pointer down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006360 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006361 ui::LogicalDisplayId::DEFAULT,
6362 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006363 // Only the first window should get the pointer down event
6364 firstWindow->consumeMotionPointerDown(1);
6365 secondWindow->assertNoEvents();
6366
6367 // Transfer touch focus to the second window
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006368 TransferFunction f = GetParam();
6369 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6370 ASSERT_TRUE(success);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006371 // The first window gets cancel and the second gets down and pointer down
6372 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006373 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6374 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6375 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006376 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006377
6378 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006379 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006380 ui::LogicalDisplayId::DEFAULT,
6381 {touchPoint, touchPoint}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006382 // The first window gets nothing and the second gets pointer up
6383 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00006384 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
6385 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
6386 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
6387 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006388
6389 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006390 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006391 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006392 // The first window gets nothing and the second gets up
6393 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006394 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6395 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006396}
6397
Arthur Hungc539dbb2022-12-08 07:45:36 +00006398TEST_P(TransferTouchFixture, TransferTouch_MultipleWallpapers) {
6399 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6400
6401 // Create a couple of windows
6402 sp<FakeWindowHandle> firstWindow =
6403 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006404 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006405 firstWindow->setDupTouchToWallpaper(true);
6406 sp<FakeWindowHandle> secondWindow =
6407 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006408 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006409 secondWindow->setDupTouchToWallpaper(true);
6410
6411 sp<FakeWindowHandle> wallpaper1 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006412 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper1",
6413 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006414 wallpaper1->setIsWallpaper(true);
6415
6416 sp<FakeWindowHandle> wallpaper2 =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006417 sp<FakeWindowHandle>::make(application, mDispatcher, "Wallpaper2",
6418 ui::LogicalDisplayId::DEFAULT);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006419 wallpaper2->setIsWallpaper(true);
6420 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006421 mDispatcher->onWindowInfosChanged({{*firstWindow->getInfo(), *wallpaper1->getInfo(),
6422 *secondWindow->getInfo(), *wallpaper2->getInfo()},
6423 {},
6424 0,
6425 0});
Arthur Hungc539dbb2022-12-08 07:45:36 +00006426
6427 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006428 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006429 AINPUT_SOURCE_TOUCHSCREEN,
6430 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006431
6432 // Only the first window should get the down event
6433 firstWindow->consumeMotionDown();
6434 secondWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006435 wallpaper1->consumeMotionDown(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006436 wallpaper2->assertNoEvents();
6437
6438 // Transfer touch focus to the second window
6439 TransferFunction f = GetParam();
6440 bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
6441 ASSERT_TRUE(success);
6442
6443 // The first window gets cancel and the second gets down
6444 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006445 secondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
6446 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
6447 wallpaper1->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, EXPECTED_WALLPAPER_FLAGS);
6448 wallpaper2->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006449 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006450
6451 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006452 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006453 ui::LogicalDisplayId::DEFAULT));
Arthur Hungc539dbb2022-12-08 07:45:36 +00006454 // The first window gets no events and the second gets up
6455 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006456 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6457 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006458 wallpaper1->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006459 wallpaper2->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
Linnan Li72352222024-04-12 18:55:57 +08006460 EXPECTED_WALLPAPER_FLAGS | AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungc539dbb2022-12-08 07:45:36 +00006461}
6462
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006463// For the cases of single pointer touch and two pointers non-split touch, the api's
Prabir Pradhan367f3432024-02-13 23:05:58 +00006464// 'transferTouchGesture' and 'transferTouchOnDisplay' are equivalent in behaviour. They only differ
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006465// for the case where there are multiple pointers split across several windows.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006466INSTANTIATE_TEST_SUITE_P(
6467 InputDispatcherTransferFunctionTests, TransferTouchFixture,
6468 ::testing::Values(
6469 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> /*ignored*/,
6470 sp<IBinder> destChannelToken) {
6471 return dispatcher->transferTouchOnDisplay(destChannelToken,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006472 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006473 },
6474 [&](const std::unique_ptr<InputDispatcher>& dispatcher, sp<IBinder> from,
6475 sp<IBinder> to) {
6476 return dispatcher->transferTouchGesture(from, to,
6477 /*isDragAndDrop=*/false);
6478 }));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006479
Prabir Pradhan367f3432024-02-13 23:05:58 +00006480TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
Chris Yea209fde2020-07-22 13:54:51 -07006481 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Svet Ganov5d3bc372020-01-26 23:11:07 -08006482
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006483 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006484 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006485 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006486 firstWindow->setFrame(Rect(0, 0, 600, 400));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006487
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10006488 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006489 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006490 ui::LogicalDisplayId::DEFAULT);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006491 secondWindow->setFrame(Rect(0, 400, 600, 800));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006492
6493 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006494 mDispatcher->onWindowInfosChanged(
6495 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Svet Ganov5d3bc372020-01-26 23:11:07 -08006496
6497 PointF pointInFirst = {300, 200};
6498 PointF pointInSecond = {300, 600};
6499
6500 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006501 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006502 AINPUT_SOURCE_TOUCHSCREEN,
6503 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006504 // Only the first window should get the down event
6505 firstWindow->consumeMotionDown();
6506 secondWindow->assertNoEvents();
6507
6508 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006509 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006510 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006511 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006512 // The first window gets a move and the second a down
6513 firstWindow->consumeMotionMove();
6514 secondWindow->consumeMotionDown();
6515
Prabir Pradhan367f3432024-02-13 23:05:58 +00006516 // Transfer touch to the second window
6517 mDispatcher->transferTouchGesture(firstWindow->getToken(), secondWindow->getToken());
Svet Ganov5d3bc372020-01-26 23:11:07 -08006518 // The first window gets cancel and the new gets pointer down (it already saw down)
6519 firstWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006520 secondWindow->consumeMotionPointerDown(1, ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006521 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006522
6523 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006524 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006525 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006526 {pointInFirst, pointInSecond}));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006527 // The first window gets nothing and the second gets pointer up
6528 firstWindow->assertNoEvents();
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +00006529 secondWindow->consumeMotionPointerUp(/*pointerIdx=*/1,
6530 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
6531 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE),
6532 WithPointerCount(2)));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006533
6534 // Send up event to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006535 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006536 ui::LogicalDisplayId::DEFAULT));
Svet Ganov5d3bc372020-01-26 23:11:07 -08006537 // The first window gets nothing and the second gets up
6538 firstWindow->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006539 secondWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6540 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Svet Ganov5d3bc372020-01-26 23:11:07 -08006541}
6542
Prabir Pradhan367f3432024-02-13 23:05:58 +00006543// Same as TransferTouch_TwoPointersSplitTouch, but using 'transferTouchOnDisplay' api.
6544// Unlike 'transferTouchGesture', calling 'transferTouchOnDisplay' when there are two windows
6545// receiving touch is not supported, so the touch should continue on those windows and the
6546// transferred-to window should get nothing.
6547TEST_F(InputDispatcherTest, TransferTouchOnDisplay_TwoPointersSplitTouch) {
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006548 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6549
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006550 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006551 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006552 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006553 firstWindow->setFrame(Rect(0, 0, 600, 400));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006554
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006555 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006556 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006557 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006558 secondWindow->setFrame(Rect(0, 400, 600, 800));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006559
6560 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006561 mDispatcher->onWindowInfosChanged(
6562 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006563
6564 PointF pointInFirst = {300, 200};
6565 PointF pointInSecond = {300, 600};
6566
6567 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006568 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006569 AINPUT_SOURCE_TOUCHSCREEN,
6570 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006571 // Only the first window should get the down event
6572 firstWindow->consumeMotionDown();
6573 secondWindow->assertNoEvents();
6574
6575 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006576 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006577 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006578 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006579 // The first window gets a move and the second a down
6580 firstWindow->consumeMotionMove();
6581 secondWindow->consumeMotionDown();
6582
6583 // Transfer touch focus to the second window
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006584 const bool transferred = mDispatcher->transferTouchOnDisplay(secondWindow->getToken(),
6585 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan367f3432024-02-13 23:05:58 +00006586 // The 'transferTouchOnDisplay' call should not succeed, because there are 2 touched windows
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006587 ASSERT_FALSE(transferred);
6588 firstWindow->assertNoEvents();
6589 secondWindow->assertNoEvents();
6590
6591 // The rest of the dispatch should proceed as normal
6592 // Send pointer up to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006593 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006594 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006595 {pointInFirst, pointInSecond}));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006596 // The first window gets MOVE and the second gets pointer up
6597 firstWindow->consumeMotionMove();
6598 secondWindow->consumeMotionUp();
6599
6600 // Send up event to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006601 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006602 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud0c6bc82021-03-13 03:14:52 +00006603 // The first window gets nothing and the second gets up
6604 firstWindow->consumeMotionUp();
6605 secondWindow->assertNoEvents();
6606}
6607
Arthur Hungabbb9d82021-09-01 14:52:30 +00006608// This case will create two windows and one mirrored window on the default display and mirror
Prabir Pradhan367f3432024-02-13 23:05:58 +00006609// two windows on the second display. It will test if 'transferTouchGesture' works fine if we put
Arthur Hungabbb9d82021-09-01 14:52:30 +00006610// the windows info of second display before default display.
Prabir Pradhan367f3432024-02-13 23:05:58 +00006611TEST_F(InputDispatcherTest, TransferTouch_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006612 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6613 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006614 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6615 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006616 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006617 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006618 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6619 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006620 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006621
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006622 sp<FakeWindowHandle> mirrorWindowInPrimary =
6623 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006624 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006625
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006626 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006627 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006628
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006629 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006630 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006631
6632 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006633 mDispatcher->onWindowInfosChanged(
6634 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6635 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6636 *secondWindowInPrimary->getInfo()},
6637 {},
6638 0,
6639 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006640
6641 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006642 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
6643 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006644 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6645
6646 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006647 firstWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006648
Prabir Pradhan367f3432024-02-13 23:05:58 +00006649 // Transfer touch
6650 ASSERT_TRUE(mDispatcher->transferTouchGesture(firstWindowInPrimary->getToken(),
6651 secondWindowInPrimary->getToken()));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006652 // The first window gets cancel.
6653 firstWindowInPrimary->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006654 secondWindowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006655 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006656
6657 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006658 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006659 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006660 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6661 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006662 secondWindowInPrimary->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +00006663 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006664
6665 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006666 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006667 {150, 50}))
6668 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6669 firstWindowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006670 secondWindowInPrimary->consumeMotionUp(ui::LogicalDisplayId::DEFAULT,
6671 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006672}
6673
Prabir Pradhan367f3432024-02-13 23:05:58 +00006674// Same as TransferTouch_CloneSurface, but this touch on the secondary display and use
6675// 'transferTouchOnDisplay' api.
6676TEST_F(InputDispatcherTest, TransferTouchOnDisplay_CloneSurface) {
Arthur Hungabbb9d82021-09-01 14:52:30 +00006677 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6678 sp<FakeWindowHandle> firstWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006679 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W1",
6680 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006681 firstWindowInPrimary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006682 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006683 sp<FakeWindowHandle>::make(application, mDispatcher, "D_1_W2",
6684 ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006685 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006686
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006687 sp<FakeWindowHandle> mirrorWindowInPrimary =
6688 firstWindowInPrimary->clone(ui::LogicalDisplayId::DEFAULT);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006689 mirrorWindowInPrimary->setFrame(Rect(0, 100, 100, 200));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006690
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006691 sp<FakeWindowHandle> firstWindowInSecondary = firstWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006692 firstWindowInSecondary->setFrame(Rect(0, 0, 100, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006693
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -07006694 sp<FakeWindowHandle> secondWindowInSecondary = secondWindowInPrimary->clone(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006695 secondWindowInPrimary->setFrame(Rect(100, 0, 200, 100));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006696
6697 // Update window info, let it find window handle of second display first.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006698 mDispatcher->onWindowInfosChanged(
6699 {{*firstWindowInSecondary->getInfo(), *secondWindowInSecondary->getInfo(),
6700 *mirrorWindowInPrimary->getInfo(), *firstWindowInPrimary->getInfo(),
6701 *secondWindowInPrimary->getInfo()},
6702 {},
6703 0,
6704 0});
Arthur Hungabbb9d82021-09-01 14:52:30 +00006705
6706 // Touch on second display.
6707 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006708 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
6709 {50, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006710 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6711
6712 // Window should receive motion event.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006713 firstWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006714
6715 // Transfer touch focus
Prabir Pradhan367f3432024-02-13 23:05:58 +00006716 ASSERT_TRUE(mDispatcher->transferTouchOnDisplay(secondWindowInSecondary->getToken(),
6717 SECOND_DISPLAY_ID));
Arthur Hungabbb9d82021-09-01 14:52:30 +00006718
6719 // The first window gets cancel.
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006720 firstWindowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
Prabir Pradhan65455c72024-02-13 21:46:41 +00006721 secondWindowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID,
6722 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006723
6724 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006725 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungabbb9d82021-09-01 14:52:30 +00006726 SECOND_DISPLAY_ID, {150, 50}))
6727 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006728 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006729 secondWindowInSecondary->consumeMotionMove(SECOND_DISPLAY_ID,
6730 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006731
6732 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006733 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {150, 50}))
Arthur Hungabbb9d82021-09-01 14:52:30 +00006734 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00006735 firstWindowInSecondary->assertNoEvents();
Prabir Pradhan65455c72024-02-13 21:46:41 +00006736 secondWindowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungabbb9d82021-09-01 14:52:30 +00006737}
6738
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006739TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006740 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006741 sp<FakeWindowHandle> window =
6742 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6743 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006744
Vishnu Nair47074b82020-08-14 11:54:47 -07006745 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006746 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07006747 setFocusedWindow(window);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006748
6749 window->consumeFocusEvent(true);
6750
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006751 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006752
6753 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006754 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006755
6756 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006757 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006758 mFakePolicy->assertUserActivityPoked();
6759}
6760
6761TEST_F(InputDispatcherTest, FocusedWindow_DisableUserActivity) {
6762 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006763 sp<FakeWindowHandle> window =
6764 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6765 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006766
6767 window->setDisableUserActivity(true);
6768 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006769 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006770 setFocusedWindow(window);
6771
6772 window->consumeFocusEvent(true);
6773
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006774 mDispatcher->notifyKey(
6775 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006776
6777 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006778 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006779
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006780 // Should have not poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006781 mDispatcher->waitForIdle();
Josep del Riob3981622023-04-18 15:49:45 +00006782 mFakePolicy->assertUserActivityNotPoked();
6783}
6784
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006785TEST_F(InputDispatcherTest, FocusedWindow_DoesNotReceivePolicyConsumedKey) {
Josep del Riob3981622023-04-18 15:49:45 +00006786 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006787 sp<FakeWindowHandle> window =
6788 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6789 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006790
6791 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006792 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006793 setFocusedWindow(window);
6794
6795 window->consumeFocusEvent(true);
6796
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006797 mFakePolicy->setConsumeKeyBeforeDispatching(true);
6798
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006799 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006800 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006801 mDispatcher->waitForIdle();
6802
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006803 // Key is not passed down
Josep del Riob3981622023-04-18 15:49:45 +00006804 window->assertNoEvents();
6805
6806 // Should have poked user activity
6807 mFakePolicy->assertUserActivityPoked();
6808}
6809
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006810TEST_F(InputDispatcherTest, FocusedWindow_PolicyConsumedKeyIgnoresDisableUserActivity) {
Josep del Riob3981622023-04-18 15:49:45 +00006811 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006812 sp<FakeWindowHandle> window =
6813 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6814 ui::LogicalDisplayId::DEFAULT);
Josep del Riob3981622023-04-18 15:49:45 +00006815
6816 window->setDisableUserActivity(true);
6817 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006818 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Josep del Riob3981622023-04-18 15:49:45 +00006819 setFocusedWindow(window);
6820
6821 window->consumeFocusEvent(true);
6822
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006823 mFakePolicy->setConsumeKeyBeforeDispatching(true);
6824
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006825 mDispatcher->notifyKey(
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006826 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
Josep del Riob3981622023-04-18 15:49:45 +00006827 mDispatcher->waitForIdle();
6828
6829 // System key is not passed down
6830 window->assertNoEvents();
6831
6832 // Should have poked user activity
6833 mFakePolicy->assertUserActivityPoked();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006834}
6835
Josep del Rioc8fdedb2024-05-21 13:32:43 +00006836class DisableUserActivityInputDispatcherTest : public InputDispatcherTest,
6837 public ::testing::WithParamInterface<bool> {};
6838
6839TEST_P(DisableUserActivityInputDispatcherTest, NotPassedToUserUserActivity) {
6840 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6841 sp<FakeWindowHandle> window =
6842 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6843 ui::LogicalDisplayId::DEFAULT);
6844
6845 window->setDisableUserActivity(GetParam());
6846
6847 window->setFocusable(true);
6848 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
6849 setFocusedWindow(window);
6850
6851 window->consumeFocusEvent(true);
6852
6853 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
6854 .keyCode(AKEYCODE_A)
6855 .policyFlags(0)
6856 .build());
6857 mDispatcher->waitForIdle();
6858
6859 // Key is not passed down
6860 window->assertNoEvents();
6861
6862 // Should not have poked user activity
6863 mFakePolicy->assertUserActivityNotPoked();
6864}
6865
6866INSTANTIATE_TEST_CASE_P(DisableUserActivity, DisableUserActivityInputDispatcherTest,
6867 ::testing::Bool());
6868
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006869TEST_F(InputDispatcherTest, InjectedTouchesPokeUserActivity) {
6870 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006871 sp<FakeWindowHandle> window =
6872 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6873 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006874
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006875 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006876
6877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07006878 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006879 ui::LogicalDisplayId::DEFAULT, {100, 100}))
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006880 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
6881
6882 window->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006883 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006884
6885 // Should have poked user activity
Siarhei Vishniakou4fd86732023-05-24 17:33:01 +00006886 mDispatcher->waitForIdle();
Siarhei Vishniakou90ee4782023-05-08 11:57:24 -07006887 mFakePolicy->assertUserActivityPoked();
6888}
6889
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006890TEST_F(InputDispatcherTest, UnfocusedWindow_DoesNotReceiveFocusEventOrKeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07006891 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006892 sp<FakeWindowHandle> window =
6893 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6894 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006895
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006896 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006897
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006898 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006899 mDispatcher->waitForIdle();
6900
6901 window->assertNoEvents();
6902}
6903
6904// If a window is touchable, but does not have focus, it should receive motion events, but not keys
6905TEST_F(InputDispatcherTest, UnfocusedWindow_ReceivesMotionsButNotKeys) {
Chris Yea209fde2020-07-22 13:54:51 -07006906 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006907 sp<FakeWindowHandle> window =
6908 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
6909 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006910
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006911 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006912
6913 // Send key
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006914 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006915 // Send motion
Prabir Pradhan678438e2023-04-13 19:32:51 +00006916 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006917 AINPUT_SOURCE_TOUCHSCREEN,
6918 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006919
6920 // Window should receive only the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006921 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01006922 window->assertNoEvents(); // Key event or focus event will not be received
6923}
6924
arthurhungea3f4fc2020-12-21 23:18:53 +08006925TEST_F(InputDispatcherTest, PointerCancel_SendCancelWhenSplitTouch) {
6926 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6927
arthurhungea3f4fc2020-12-21 23:18:53 +08006928 sp<FakeWindowHandle> firstWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006929 sp<FakeWindowHandle>::make(application, mDispatcher, "First Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006930 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006931 firstWindow->setFrame(Rect(0, 0, 600, 400));
arthurhungea3f4fc2020-12-21 23:18:53 +08006932
arthurhungea3f4fc2020-12-21 23:18:53 +08006933 sp<FakeWindowHandle> secondWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07006934 sp<FakeWindowHandle>::make(application, mDispatcher, "Second Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006935 ui::LogicalDisplayId::DEFAULT);
arthurhungea3f4fc2020-12-21 23:18:53 +08006936 secondWindow->setFrame(Rect(0, 400, 600, 800));
arthurhungea3f4fc2020-12-21 23:18:53 +08006937
6938 // Add the windows to the dispatcher
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006939 mDispatcher->onWindowInfosChanged(
6940 {{*firstWindow->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
arthurhungea3f4fc2020-12-21 23:18:53 +08006941
6942 PointF pointInFirst = {300, 200};
6943 PointF pointInSecond = {300, 600};
6944
6945 // Send down to the first window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006946 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006947 AINPUT_SOURCE_TOUCHSCREEN,
6948 ui::LogicalDisplayId::DEFAULT, {pointInFirst}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006949 // Only the first window should get the down event
6950 firstWindow->consumeMotionDown();
6951 secondWindow->assertNoEvents();
6952
6953 // Send down to the second window
Prabir Pradhan678438e2023-04-13 19:32:51 +00006954 mDispatcher->notifyMotion(generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006955 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +00006956 {pointInFirst, pointInSecond}));
arthurhungea3f4fc2020-12-21 23:18:53 +08006957 // The first window gets a move and the second a down
6958 firstWindow->consumeMotionMove();
6959 secondWindow->consumeMotionDown();
6960
6961 // Send pointer cancel to the second window
6962 NotifyMotionArgs pointerUpMotionArgs =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006963 generateMotionArgs(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN,
6964 ui::LogicalDisplayId::DEFAULT, {pointInFirst, pointInSecond});
arthurhungea3f4fc2020-12-21 23:18:53 +08006965 pointerUpMotionArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
Prabir Pradhan678438e2023-04-13 19:32:51 +00006966 mDispatcher->notifyMotion(pointerUpMotionArgs);
arthurhungea3f4fc2020-12-21 23:18:53 +08006967 // The first window gets move and the second gets cancel.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006968 firstWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
6969 secondWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
arthurhungea3f4fc2020-12-21 23:18:53 +08006970
6971 // Send up event.
Prabir Pradhan678438e2023-04-13 19:32:51 +00006972 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006973 ui::LogicalDisplayId::DEFAULT));
arthurhungea3f4fc2020-12-21 23:18:53 +08006974 // The first window gets up and the second gets nothing.
6975 firstWindow->consumeMotionUp();
6976 secondWindow->assertNoEvents();
6977}
6978
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006979TEST_F(InputDispatcherTest, SendTimeline_DoesNotCrashDispatcher) {
6980 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
6981
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07006982 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
6983 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07006984 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006985 std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
6986 graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 2;
6987 graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 3;
6988
Harry Cutts33476232023-01-30 19:57:29 +00006989 window->sendTimeline(/*inputEventId=*/1, graphicsTimeline);
Siarhei Vishniakouf94ae022021-02-04 01:23:17 +00006990 window->assertNoEvents();
6991 mDispatcher->waitForIdle();
6992}
6993
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08006994using InputDispatcherMonitorTest = InputDispatcherTest;
6995
Siarhei Vishniakouca205502021-07-16 21:31:58 +00006996/**
6997 * Two entities that receive touch: A window, and a global monitor.
6998 * The touch goes to the window, and then the window disappears.
6999 * The monitor does not get cancel right away. But if more events come in, the touch gets canceled
7000 * for the monitor, as well.
7001 * 1. foregroundWindow
7002 * 2. monitor <-- global monitor (doesn't observe z order, receives all events)
7003 */
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007004TEST_F(InputDispatcherMonitorTest, MonitorTouchIsCanceledWhenForegroundWindowDisappears) {
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007005 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007006 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7007 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007008
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007009 FakeMonitorReceiver monitor =
7010 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007011
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007012 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007013 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007014 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7015 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007016 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7017
7018 // Both the foreground window and the global monitor should receive the touch down
7019 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007020 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007021
7022 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007023 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007024 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007025 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
7026
7027 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007028 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007029
7030 // Now the foreground window goes away
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007031 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007032 window->consumeMotionCancel();
7033 monitor.assertNoEvents(); // Global monitor does not get a cancel yet
7034
7035 // If more events come in, there will be no more foreground window to send them to. This will
7036 // cause a cancel for the monitor, as well.
7037 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007038 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007039 ui::LogicalDisplayId::DEFAULT, {120, 200}))
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007040 << "Injection should fail because the window was removed";
7041 window->assertNoEvents();
7042 // Global monitor now gets the cancel
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007043 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouca205502021-07-16 21:31:58 +00007044}
7045
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007046TEST_F(InputDispatcherMonitorTest, ReceivesMotionEvents) {
Chris Yea209fde2020-07-22 13:54:51 -07007047 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007048 sp<FakeWindowHandle> window =
7049 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7050 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007051 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007052
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007053 FakeMonitorReceiver monitor =
7054 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007055
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007056 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007057 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7058 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007059 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007060 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7061 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007062}
7063
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007064TEST_F(InputDispatcherMonitorTest, MonitorCannotPilferPointers) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007065 FakeMonitorReceiver monitor =
7066 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007067
Chris Yea209fde2020-07-22 13:54:51 -07007068 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007069 sp<FakeWindowHandle> window =
7070 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7071 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007072 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Michael Wright3a240c42019-12-10 20:53:41 +00007073
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007074 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007075 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7076 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007077 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007078 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7079 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007080
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007081 // Pilfer pointers from the monitor.
7082 // This should not do anything and the window should continue to receive events.
7083 EXPECT_NE(OK, mDispatcher->pilferPointers(monitor.getToken()));
Michael Wright3a240c42019-12-10 20:53:41 +00007084
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007085 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007086 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007087 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007088 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007089
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007090 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
7091 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Michael Wright3a240c42019-12-10 20:53:41 +00007092}
7093
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007094TEST_F(InputDispatcherMonitorTest, NoWindowTransform) {
Evan Rosky84f07f02021-04-16 10:42:42 -07007095 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007096 sp<FakeWindowHandle> window =
7097 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7098 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007099 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Evan Rosky84f07f02021-04-16 10:42:42 -07007100 window->setWindowOffset(20, 40);
7101 window->setWindowTransform(0, 1, -1, 0);
7102
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007103 FakeMonitorReceiver monitor =
7104 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Evan Rosky84f07f02021-04-16 10:42:42 -07007105
7106 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007107 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7108 ui::LogicalDisplayId::DEFAULT))
Evan Rosky84f07f02021-04-16 10:42:42 -07007109 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007110 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007111 std::unique_ptr<MotionEvent> event = monitor.consumeMotion();
7112 ASSERT_NE(nullptr, event);
Evan Rosky84f07f02021-04-16 10:42:42 -07007113 // Even though window has transform, gesture monitor must not.
7114 ASSERT_EQ(ui::Transform(), event->getTransform());
7115}
7116
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007117TEST_F(InputDispatcherMonitorTest, InjectionFailsWithNoWindow) {
Arthur Hungb3307ee2021-10-14 10:57:37 +00007118 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007119 FakeMonitorReceiver monitor =
7120 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungb3307ee2021-10-14 10:57:37 +00007121
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007122 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007123 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7124 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08007125 << "Injection should fail if there is a monitor, but no touchable window";
7126 monitor.assertNoEvents();
Arthur Hungb3307ee2021-10-14 10:57:37 +00007127}
7128
Linnan Lid8150952024-01-26 18:07:17 +00007129/**
7130 * Two displays
7131 * The first monitor has a foreground window, a monitor
7132 * The second window has only one monitor.
7133 * We first inject a Down event into the first display, this injection should succeed and both
7134 * the foreground window and monitor should receive a down event, then inject a Down event into
7135 * the second display as well, this injection should fail, at this point, the first display
7136 * window and monitor should not receive a cancel or any other event.
7137 * Continue to inject Move and UP events to the first display, the events should be received
7138 * normally by the foreground window and monitor.
7139 */
7140TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCanceledWhenAnotherEmptyDisplayReceiveEvents) {
7141 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007142 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7143 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007144
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007145 FakeMonitorReceiver monitor =
7146 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007147 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7148
7149 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7150 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007151 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7152 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007153 << "The down event injected into the first display should succeed";
7154
7155 window->consumeMotionDown();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007156 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007157
7158 ASSERT_EQ(InputEventInjectionResult::FAILED,
7159 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7160 {100, 200}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007161 << "The down event injected into the second display should fail since there's no "
7162 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007163
7164 // Continue to inject event to first display.
7165 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7166 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007167 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007168 << "The move event injected into the first display should succeed";
7169
7170 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007171 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007172
7173 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007174 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007175 {110, 220}))
7176 << "The up event injected into the first display should succeed";
7177
7178 window->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007179 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007180
7181 window->assertNoEvents();
7182 monitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007183 secondMonitor.assertNoEvents();
7184}
7185
7186/**
7187 * Two displays
7188 * There is a monitor and foreground window on each display.
7189 * First, we inject down events into each of the two displays, at this point, the foreground windows
7190 * and monitors on both displays should receive down events.
7191 * At this point, the foreground window of the second display goes away, the gone window should
7192 * receive the cancel event, and the other windows and monitors should not receive any events.
7193 * Inject a move event into the second display. At this point, the injection should fail because
7194 * the second display no longer has a foreground window. At this point, the monitor on the second
7195 * display should receive a cancel event, and any windows or monitors on the first display should
7196 * not receive any events, and any subsequent injection of events into the second display should
7197 * also fail.
7198 * Continue to inject events into the first display, and the events should all be injected
7199 * successfully and received normally.
7200 */
7201TEST_F(InputDispatcherMonitorTest, MonitorTouchIsNotCancelWhenAnotherDisplayMonitorTouchCanceled) {
7202 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007203 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7204 ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007205 sp<FakeWindowHandle> secondWindow =
7206 sp<FakeWindowHandle>::make(application, mDispatcher, "SecondForeground",
7207 SECOND_DISPLAY_ID);
7208
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007209 FakeMonitorReceiver monitor =
7210 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007211 FakeMonitorReceiver secondMonitor = FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
7212
7213 // There is a foreground window on both displays.
7214 mDispatcher->onWindowInfosChanged({{*window->getInfo(), *secondWindow->getInfo()}, {}, 0, 0});
7215 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007216 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7217 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007218 << "The down event injected into the first display should succeed";
7219
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007220 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
7221 monitor.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007222
7223 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7224 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7225 {100, 200}))
7226 << "The down event injected into the second display should succeed";
7227
Linnan Lid8150952024-01-26 18:07:17 +00007228 secondWindow->consumeMotionDown(SECOND_DISPLAY_ID);
7229 secondMonitor.consumeMotionDown(SECOND_DISPLAY_ID);
7230
7231 // Now second window is gone away.
7232 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
7233
7234 // The gone window should receive a cancel, and the monitor on the second display should not
7235 // receive any events.
Linnan Lid8150952024-01-26 18:07:17 +00007236 secondWindow->consumeMotionCancel(SECOND_DISPLAY_ID);
7237 secondMonitor.assertNoEvents();
7238
7239 ASSERT_EQ(InputEventInjectionResult::FAILED,
7240 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
7241 SECOND_DISPLAY_ID, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007242 << "The move event injected into the second display should fail because there's no "
7243 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007244 // Now the monitor on the second display should receive a cancel event.
7245 secondMonitor.consumeMotionCancel(SECOND_DISPLAY_ID);
Linnan Lid8150952024-01-26 18:07:17 +00007246
7247 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7248 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007249 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007250 << "The move event injected into the first display should succeed";
7251
7252 window->consumeMotionMove();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007253 monitor.consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007254
7255 ASSERT_EQ(InputEventInjectionResult::FAILED,
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007256 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID,
7257 {110, 220}))
7258 << "The up event injected into the second display should fail because there's no "
7259 "touchable window";
Linnan Lid8150952024-01-26 18:07:17 +00007260
7261 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007262 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Lid8150952024-01-26 18:07:17 +00007263 {110, 220}))
7264 << "The up event injected into the first display should succeed";
7265
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007266 window->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
7267 monitor.consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007268
Linnan Lid8150952024-01-26 18:07:17 +00007269 window->assertNoEvents();
7270 monitor.assertNoEvents();
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007271 secondWindow->assertNoEvents();
7272 secondMonitor.assertNoEvents();
Linnan Lid8150952024-01-26 18:07:17 +00007273}
7274
7275/**
7276 * One display with transform
7277 * There is a foreground window and a monitor on the display
7278 * Inject down event and move event sequentially, the foreground window and monitor can receive down
7279 * event and move event, then let the foreground window go away, the foreground window receives
7280 * cancel event, inject move event again, the monitor receives cancel event, all the events received
7281 * by the monitor should be with the same transform as the display
7282 */
7283TEST_F(InputDispatcherMonitorTest, MonitorTouchCancelEventWithDisplayTransform) {
7284 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007285 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Foreground",
7286 ui::LogicalDisplayId::DEFAULT);
7287 FakeMonitorReceiver monitor =
7288 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Linnan Lid8150952024-01-26 18:07:17 +00007289
7290 ui::Transform transform;
7291 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7292
7293 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007294 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Linnan Lid8150952024-01-26 18:07:17 +00007295 displayInfo.transform = transform;
7296
7297 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
7298
7299 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007300 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
7301 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Linnan Lid8150952024-01-26 18:07:17 +00007302 << "The down event injected should succeed";
7303
7304 window->consumeMotionDown();
7305 std::unique_ptr<MotionEvent> downMotionEvent = monitor.consumeMotion();
7306 EXPECT_EQ(transform, downMotionEvent->getTransform());
7307 EXPECT_EQ(AMOTION_EVENT_ACTION_DOWN, downMotionEvent->getAction());
7308
7309 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7310 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007311 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007312 << "The move event injected should succeed";
7313
7314 window->consumeMotionMove();
7315 std::unique_ptr<MotionEvent> moveMotionEvent = monitor.consumeMotion();
7316 EXPECT_EQ(transform, moveMotionEvent->getTransform());
7317 EXPECT_EQ(AMOTION_EVENT_ACTION_MOVE, moveMotionEvent->getAction());
7318
7319 // Let foreground window gone
7320 mDispatcher->onWindowInfosChanged({{}, {displayInfo}, 0, 0});
7321
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007322 // Foreground window should receive a cancel event, but not the monitor.
Linnan Lid8150952024-01-26 18:07:17 +00007323 window->consumeMotionCancel();
Linnan Lid8150952024-01-26 18:07:17 +00007324
7325 ASSERT_EQ(InputEventInjectionResult::FAILED,
7326 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007327 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Linnan Lid8150952024-01-26 18:07:17 +00007328 << "The move event injected should failed";
7329 // Now foreground should not receive any events, but monitor should receive a cancel event
7330 // with transform that same as display's display.
Linnan Lid8150952024-01-26 18:07:17 +00007331 std::unique_ptr<MotionEvent> cancelMotionEvent = monitor.consumeMotion();
7332 EXPECT_EQ(transform, cancelMotionEvent->getTransform());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007333 EXPECT_EQ(ui::LogicalDisplayId::DEFAULT, cancelMotionEvent->getDisplayId());
Linnan Lid8150952024-01-26 18:07:17 +00007334 EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, cancelMotionEvent->getAction());
7335
7336 // Other event inject to this display should fail.
7337 ASSERT_EQ(InputEventInjectionResult::FAILED,
7338 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007339 ui::LogicalDisplayId::DEFAULT, {110, 220}))
Prabir Pradhana0d43d42024-01-30 00:27:08 +00007340 << "The up event injected should fail because the touched window was removed";
Linnan Lid8150952024-01-26 18:07:17 +00007341 window->assertNoEvents();
7342 monitor.assertNoEvents();
7343}
7344
chaviw81e2bb92019-12-18 15:03:51 -08007345TEST_F(InputDispatcherTest, TestMoveEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007346 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007347 sp<FakeWindowHandle> window =
7348 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
7349 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007350
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007351 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
chaviw81e2bb92019-12-18 15:03:51 -08007352
7353 NotifyMotionArgs motionArgs =
7354 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007355 ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007356
Prabir Pradhan678438e2023-04-13 19:32:51 +00007357 mDispatcher->notifyMotion(motionArgs);
chaviw81e2bb92019-12-18 15:03:51 -08007358 // Window should receive motion down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007359 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
chaviw81e2bb92019-12-18 15:03:51 -08007360
7361 motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
Garfield Tanc51d1ba2020-01-28 13:24:04 -08007362 motionArgs.id += 1;
chaviw81e2bb92019-12-18 15:03:51 -08007363 motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
7364 motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
7365 motionArgs.pointerCoords[0].getX() - 10);
7366
Prabir Pradhan678438e2023-04-13 19:32:51 +00007367 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007368 window->consumeMotionMove(ui::LogicalDisplayId::DEFAULT, /*expectedFlags=*/0);
chaviw81e2bb92019-12-18 15:03:51 -08007369}
7370
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007371/**
7372 * Dispatcher has touch mode enabled by default. Typically, the policy overrides that value to
7373 * the device default right away. In the test scenario, we check both the default value,
7374 * and the action of enabling / disabling.
7375 */
7376TEST_F(InputDispatcherTest, TouchModeState_IsSentToApps) {
Chris Yea209fde2020-07-22 13:54:51 -07007377 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007378 sp<FakeWindowHandle> window =
7379 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7380 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekea47acb2021-12-23 12:41:25 -08007381 const WindowInfo& windowInfo = *window->getInfo();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007382
7383 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007384 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007385 window->setFocusable(true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007386
7387 SCOPED_TRACE("Check default value of touch mode");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007388 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007389 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007390 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007391
7392 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007393 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007394 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007395 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007396
7397 SCOPED_TRACE("Disable touch mode");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007398 mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007399 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007400 window->consumeTouchModeEvent(false);
Vishnu Nair47074b82020-08-14 11:54:47 -07007401 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007402 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007403 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007404 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007405
7406 SCOPED_TRACE("Remove the window to trigger focus loss");
Vishnu Nair47074b82020-08-14 11:54:47 -07007407 window->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007408 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Harry Cutts33476232023-01-30 19:57:29 +00007409 window->consumeFocusEvent(/*hasFocus=*/false, /*inTouchMode=*/false);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007410
7411 SCOPED_TRACE("Enable touch mode again");
Antonio Kantekea47acb2021-12-23 12:41:25 -08007412 mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007413 /*hasPermission=*/true, ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +00007414 window->consumeTouchModeEvent(true);
Vishnu Nair47074b82020-08-14 11:54:47 -07007415 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007416 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007417 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +00007418 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01007419
7420 window->assertNoEvents();
7421}
7422
Gang Wange9087892020-01-07 12:17:14 -05007423TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007424 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007425 sp<FakeWindowHandle> window =
7426 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7427 ui::LogicalDisplayId::DEFAULT);
Gang Wange9087892020-01-07 12:17:14 -05007428
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007429 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07007430 window->setFocusable(true);
Gang Wange9087892020-01-07 12:17:14 -05007431
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007432 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007433 setFocusedWindow(window);
7434
Harry Cutts33476232023-01-30 19:57:29 +00007435 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Gang Wange9087892020-01-07 12:17:14 -05007436
Prabir Pradhan678438e2023-04-13 19:32:51 +00007437 const NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
7438 mDispatcher->notifyKey(keyArgs);
Gang Wange9087892020-01-07 12:17:14 -05007439
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007440 std::unique_ptr<KeyEvent> event = window->consumeKey();
7441 ASSERT_NE(event, nullptr);
7442 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Gang Wange9087892020-01-07 12:17:14 -05007443 ASSERT_NE(verified, nullptr);
7444 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
7445
7446 ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
7447 ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
7448 ASSERT_EQ(keyArgs.source, verified->source);
7449 ASSERT_EQ(keyArgs.displayId, verified->displayId);
7450
7451 const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
7452
7453 ASSERT_EQ(keyArgs.action, verifiedKey.action);
Gang Wange9087892020-01-07 12:17:14 -05007454 ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007455 ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
Gang Wange9087892020-01-07 12:17:14 -05007456 ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
7457 ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
7458 ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
7459 ASSERT_EQ(0, verifiedKey.repeatCount);
7460}
7461
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007462TEST_F(InputDispatcherTest, VerifyInputEvent_MotionEvent) {
Chris Yea209fde2020-07-22 13:54:51 -07007463 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007464 sp<FakeWindowHandle> window =
7465 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
7466 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007467
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007468 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007469
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007470 ui::Transform transform;
7471 transform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
7472
7473 gui::DisplayInfo displayInfo;
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007474 displayInfo.displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007475 displayInfo.transform = transform;
7476
Patrick Williamsd828f302023-04-28 17:52:08 -05007477 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {displayInfo}, 0, 0});
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007478
Prabir Pradhan678438e2023-04-13 19:32:51 +00007479 const NotifyMotionArgs motionArgs =
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007480 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007481 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan678438e2023-04-13 19:32:51 +00007482 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007483
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08007484 std::unique_ptr<MotionEvent> event = window->consumeMotionEvent();
7485 ASSERT_NE(nullptr, event);
7486 std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007487 ASSERT_NE(verified, nullptr);
7488 ASSERT_EQ(verified->type, VerifiedInputEvent::Type::MOTION);
7489
7490 EXPECT_EQ(motionArgs.eventTime, verified->eventTimeNanos);
7491 EXPECT_EQ(motionArgs.deviceId, verified->deviceId);
7492 EXPECT_EQ(motionArgs.source, verified->source);
7493 EXPECT_EQ(motionArgs.displayId, verified->displayId);
7494
7495 const VerifiedMotionEvent& verifiedMotion = static_cast<const VerifiedMotionEvent&>(*verified);
7496
Prabir Pradhanb5cb9572021-09-24 06:35:16 -07007497 const vec2 rawXY =
7498 MotionEvent::calculateTransformedXY(motionArgs.source, transform,
7499 motionArgs.pointerCoords[0].getXYValue());
7500 EXPECT_EQ(rawXY.x, verifiedMotion.rawX);
7501 EXPECT_EQ(rawXY.y, verifiedMotion.rawY);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007502 EXPECT_EQ(motionArgs.action & AMOTION_EVENT_ACTION_MASK, verifiedMotion.actionMasked);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007503 EXPECT_EQ(motionArgs.flags & VERIFIED_MOTION_EVENT_FLAGS, verifiedMotion.flags);
Siarhei Vishniakouf355bf92021-12-09 10:43:21 -08007504 EXPECT_EQ(motionArgs.downTime, verifiedMotion.downTimeNanos);
Siarhei Vishniakou47040bf2020-02-28 15:03:13 -08007505 EXPECT_EQ(motionArgs.metaState, verifiedMotion.metaState);
7506 EXPECT_EQ(motionArgs.buttonState, verifiedMotion.buttonState);
7507}
7508
chaviw09c8d2d2020-08-24 15:48:26 -07007509/**
7510 * Ensure that separate calls to sign the same data are generating the same key.
7511 * We avoid asserting against INVALID_HMAC. Since the key is random, there is a non-zero chance
7512 * that a specific key and data combination would produce INVALID_HMAC, which would cause flaky
7513 * tests.
7514 */
7515TEST_F(InputDispatcherTest, GeneratedHmac_IsConsistent) {
7516 KeyEvent event = getTestKeyEvent();
7517 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7518
7519 std::array<uint8_t, 32> hmac1 = mDispatcher->sign(verifiedEvent);
7520 std::array<uint8_t, 32> hmac2 = mDispatcher->sign(verifiedEvent);
7521 ASSERT_EQ(hmac1, hmac2);
7522}
7523
7524/**
7525 * Ensure that changes in VerifiedKeyEvent produce a different hmac.
7526 */
7527TEST_F(InputDispatcherTest, GeneratedHmac_ChangesWhenFieldsChange) {
7528 KeyEvent event = getTestKeyEvent();
7529 VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEvent(event);
7530 std::array<uint8_t, 32> initialHmac = mDispatcher->sign(verifiedEvent);
7531
7532 verifiedEvent.deviceId += 1;
7533 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7534
7535 verifiedEvent.source += 1;
7536 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7537
7538 verifiedEvent.eventTimeNanos += 1;
7539 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7540
Linnan Li13bf76a2024-05-05 19:18:02 +08007541 verifiedEvent.displayId = ui::LogicalDisplayId{verifiedEvent.displayId.val() + 1};
chaviw09c8d2d2020-08-24 15:48:26 -07007542 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7543
7544 verifiedEvent.action += 1;
7545 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7546
7547 verifiedEvent.downTimeNanos += 1;
7548 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7549
7550 verifiedEvent.flags += 1;
7551 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7552
7553 verifiedEvent.keyCode += 1;
7554 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7555
7556 verifiedEvent.scanCode += 1;
7557 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7558
7559 verifiedEvent.metaState += 1;
7560 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7561
7562 verifiedEvent.repeatCount += 1;
7563 ASSERT_NE(initialHmac, mDispatcher->sign(verifiedEvent));
7564}
7565
Vishnu Nair958da932020-08-21 17:12:37 -07007566TEST_F(InputDispatcherTest, SetFocusedWindow) {
7567 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007568 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7569 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007570 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007571 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7572 ui::LogicalDisplayId::DEFAULT);
7573 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007574
7575 // Top window is also focusable but is not granted focus.
7576 windowTop->setFocusable(true);
7577 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007578 mDispatcher->onWindowInfosChanged(
7579 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007580 setFocusedWindow(windowSecond);
7581
7582 windowSecond->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007583 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007584 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007585
7586 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007587 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007588 windowTop->assertNoEvents();
7589}
7590
7591TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestInvalidChannel) {
7592 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007593 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7594 ui::LogicalDisplayId::DEFAULT);
7595 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007596
7597 window->setFocusable(true);
7598 // Release channel for window is no longer valid.
7599 window->releaseChannel();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007600 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007601 setFocusedWindow(window);
7602
7603 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007604 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007605
7606 // window channel is invalid, so it should not receive any input event.
7607 window->assertNoEvents();
7608}
7609
7610TEST_F(InputDispatcherTest, SetFocusedWindow_DropRequestNoFocusableWindow) {
7611 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007612 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7613 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007614 window->setFocusable(false);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007615 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007616
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007617 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007618 setFocusedWindow(window);
7619
7620 // Test inject a key down, should timeout.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007621 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Vishnu Nair958da932020-08-21 17:12:37 -07007622
Prabir Pradhan76bdecb2022-01-31 11:14:15 -08007623 // window is not focusable, so it should not receive any input event.
Vishnu Nair958da932020-08-21 17:12:37 -07007624 window->assertNoEvents();
7625}
7626
7627TEST_F(InputDispatcherTest, SetFocusedWindow_CheckFocusedToken) {
7628 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007629 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7630 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007631 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007632 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7633 ui::LogicalDisplayId::DEFAULT);
7634 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007635
7636 windowTop->setFocusable(true);
7637 windowSecond->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007638 mDispatcher->onWindowInfosChanged(
7639 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007640 setFocusedWindow(windowTop);
7641 windowTop->consumeFocusEvent(true);
7642
Chavi Weingarten847e8512023-03-29 00:26:09 +00007643 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007644 mDispatcher->onWindowInfosChanged(
7645 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007646 windowSecond->consumeFocusEvent(true);
7647 windowTop->consumeFocusEvent(false);
7648
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007649 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007650 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007651
7652 // Focused window should receive event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007653 windowSecond->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007654}
7655
Chavi Weingarten847e8512023-03-29 00:26:09 +00007656TEST_F(InputDispatcherTest, SetFocusedWindow_TransferFocusTokenNotFocusable) {
Vishnu Nair958da932020-08-21 17:12:37 -07007657 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007658 sp<FakeWindowHandle> windowTop = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7659 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007660 sp<FakeWindowHandle> windowSecond =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007661 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7662 ui::LogicalDisplayId::DEFAULT);
7663 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007664
7665 windowTop->setFocusable(true);
Chavi Weingarten847e8512023-03-29 00:26:09 +00007666 windowSecond->setFocusable(false);
7667 windowTop->editInfo()->focusTransferTarget = windowSecond->getToken();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007668 mDispatcher->onWindowInfosChanged(
7669 {{*windowTop->getInfo(), *windowSecond->getInfo()}, {}, 0, 0});
Chavi Weingarten847e8512023-03-29 00:26:09 +00007670 setFocusedWindow(windowTop);
7671 windowTop->consumeFocusEvent(true);
Vishnu Nair958da932020-08-21 17:12:37 -07007672
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007673 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Chavi Weingarten847e8512023-03-29 00:26:09 +00007674 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07007675
7676 // Event should be dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007677 windowTop->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -07007678 windowSecond->assertNoEvents();
7679}
7680
7681TEST_F(InputDispatcherTest, SetFocusedWindow_DeferInvisibleWindow) {
7682 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007683 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
7684 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007685 sp<FakeWindowHandle> previousFocusedWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07007686 sp<FakeWindowHandle>::make(application, mDispatcher, "previousFocusedWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007687 ui::LogicalDisplayId::DEFAULT);
7688 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair958da932020-08-21 17:12:37 -07007689
7690 window->setFocusable(true);
7691 previousFocusedWindow->setFocusable(true);
7692 window->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007693 mDispatcher->onWindowInfosChanged(
7694 {{*window->getInfo(), *previousFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007695 setFocusedWindow(previousFocusedWindow);
7696 previousFocusedWindow->consumeFocusEvent(true);
7697
7698 // Requesting focus on invisible window takes focus from currently focused window.
7699 setFocusedWindow(window);
7700 previousFocusedWindow->consumeFocusEvent(false);
7701
7702 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08007703 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07007704 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007705 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -07007706
7707 // Window does not get focus event or key down.
7708 window->assertNoEvents();
7709
7710 // Window becomes visible.
7711 window->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007712 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07007713
7714 // Window receives focus event.
7715 window->consumeFocusEvent(true);
7716 // Focused window receives key down.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007717 window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07007718}
7719
Vishnu Nair599f1412021-06-21 10:39:58 -07007720TEST_F(InputDispatcherTest, DisplayRemoved) {
7721 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007722 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "window",
7723 ui::LogicalDisplayId::DEFAULT);
7724 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair599f1412021-06-21 10:39:58 -07007725
7726 // window is granted focus.
7727 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007728 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair599f1412021-06-21 10:39:58 -07007729 setFocusedWindow(window);
7730 window->consumeFocusEvent(true);
7731
7732 // When a display is removed window loses focus.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007733 mDispatcher->displayRemoved(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair599f1412021-06-21 10:39:58 -07007734 window->consumeFocusEvent(false);
7735}
7736
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007737/**
7738 * Launch two windows, with different owners. One window (slipperyExitWindow) has Flag::SLIPPERY,
7739 * and overlaps the other window, slipperyEnterWindow. The window 'slipperyExitWindow' is on top
7740 * of the 'slipperyEnterWindow'.
7741 *
7742 * Inject touch down into the top window. Upon receipt of the DOWN event, move the window in such
7743 * a way so that the touched location is no longer covered by the top window.
7744 *
7745 * Next, inject a MOVE event. Because the top window already moved earlier, this event is now
7746 * positioned over the bottom (slipperyEnterWindow) only. And because the top window had
7747 * Flag::SLIPPERY, this will cause the top window to lose the touch event (it will receive
7748 * ACTION_CANCEL instead), and the bottom window will receive a newly generated gesture (starting
7749 * with ACTION_DOWN).
7750 * Thus, the touch has been transferred from the top window into the bottom window, because the top
7751 * window moved itself away from the touched location and had Flag::SLIPPERY.
7752 *
7753 * Even though the top window moved away from the touched location, it is still obscuring the bottom
7754 * window. It's just not obscuring it at the touched location. That means, FLAG_WINDOW_IS_PARTIALLY_
7755 * OBSCURED should be set for the MotionEvent that reaches the bottom window.
7756 *
7757 * In this test, we ensure that the event received by the bottom window has
7758 * FLAG_WINDOW_IS_PARTIALLY_OBSCURED.
7759 */
7760TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00007761 constexpr gui::Pid SLIPPERY_PID{WINDOW_PID.val() + 1};
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00007762 constexpr gui::Uid SLIPPERY_UID{WINDOW_UID.val() + 1};
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007763
7764 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007765 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007766
7767 sp<FakeWindowHandle> slipperyExitWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007768 sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
7769 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -08007770 slipperyExitWindow->setSlippery(true);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007771 // Make sure this one overlaps the bottom window
7772 slipperyExitWindow->setFrame(Rect(25, 25, 75, 75));
7773 // Change the owner uid/pid of the window so that it is considered to be occluding the bottom
7774 // one. Windows with the same owner are not considered to be occluding each other.
7775 slipperyExitWindow->setOwnerInfo(SLIPPERY_PID, SLIPPERY_UID);
7776
7777 sp<FakeWindowHandle> slipperyEnterWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007778 sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
7779 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007780 slipperyExitWindow->setFrame(Rect(0, 0, 100, 100));
7781
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007782 mDispatcher->onWindowInfosChanged(
7783 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007784
7785 // Use notifyMotion instead of injecting to avoid dealing with injection permissions
Prabir Pradhan678438e2023-04-13 19:32:51 +00007786 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007787 AINPUT_SOURCE_TOUCHSCREEN,
7788 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007789 slipperyExitWindow->consumeMotionDown();
7790 slipperyExitWindow->setFrame(Rect(70, 70, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007791 mDispatcher->onWindowInfosChanged(
7792 {{*slipperyExitWindow->getInfo(), *slipperyEnterWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007793
Prabir Pradhan678438e2023-04-13 19:32:51 +00007794 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_MOVE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007795 AINPUT_SOURCE_TOUCHSCREEN,
7796 ui::LogicalDisplayId::DEFAULT, {{51, 51}}));
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007797
7798 slipperyExitWindow->consumeMotionCancel();
7799
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007800 slipperyEnterWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10007801 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
7802}
7803
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007804/**
7805 * Two windows, one on the left and another on the right. The left window is slippery. The right
7806 * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the
7807 * touch moves from the left window into the right window, the gesture should continue to go to the
7808 * left window. Touch shouldn't slip because the right window can't receive touches. This test
7809 * reproduces a crash.
7810 */
7811TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) {
7812 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7813
7814 sp<FakeWindowHandle> leftSlipperyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007815 sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
7816 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007817 leftSlipperyWindow->setSlippery(true);
7818 leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100));
7819
7820 sp<FakeWindowHandle> rightDropTouchesWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007821 sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
7822 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007823 rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100));
7824 rightDropTouchesWindow->setDropInput(true);
7825
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07007826 mDispatcher->onWindowInfosChanged(
7827 {{*leftSlipperyWindow->getInfo(), *rightDropTouchesWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouafa08cc2023-05-08 22:35:50 -07007828
7829 // Start touch in the left window
7830 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7831 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7832 .build());
7833 leftSlipperyWindow->consumeMotionDown();
7834
7835 // And move it into the right window
7836 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7837 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7838 .build());
7839
7840 // Since the right window isn't eligible to receive input, touch does not slip.
7841 // The left window continues to receive the gesture.
7842 leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7843 rightDropTouchesWindow->assertNoEvents();
7844}
7845
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007846/**
7847 * A single window is on screen first. Touch is injected into that window. Next, a second window
7848 * appears. Since the first window is slippery, touch will move from the first window to the second.
7849 */
7850TEST_F(InputDispatcherTest, InjectedTouchSlips) {
7851 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7852 sp<FakeWindowHandle> originalWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007853 sp<FakeWindowHandle>::make(application, mDispatcher, "Original",
7854 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007855 originalWindow->setFrame(Rect(0, 0, 200, 200));
7856 originalWindow->setSlippery(true);
7857
7858 sp<FakeWindowHandle> appearingWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007859 sp<FakeWindowHandle>::make(application, mDispatcher, "Appearing",
7860 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07007861 appearingWindow->setFrame(Rect(0, 0, 200, 200));
7862
7863 mDispatcher->onWindowInfosChanged({{*originalWindow->getInfo()}, {}, 0, 0});
7864
7865 // Touch down on the original window
7866 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7867 injectMotionEvent(*mDispatcher,
7868 MotionEventBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7869 .pointer(PointerBuilder(1, ToolType::FINGER).x(100).y(100))
7870 .build()));
7871 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7872
7873 // Now, a new window appears. This could be, for example, a notification shade that appears
7874 // after user starts to drag down on the launcher window.
7875 mDispatcher->onWindowInfosChanged(
7876 {{*appearingWindow->getInfo(), *originalWindow->getInfo()}, {}, 0, 0});
7877 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7878 injectMotionEvent(*mDispatcher,
7879 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7880 .pointer(PointerBuilder(1, ToolType::FINGER).x(110).y(110))
7881 .build()));
7882 originalWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
7883 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
7884 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
7885 injectMotionEvent(*mDispatcher,
7886 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7887 .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
7888 .build()));
7889 appearingWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
7890
7891 originalWindow->assertNoEvents();
7892 appearingWindow->assertNoEvents();
7893}
7894
Linnan Li49b2b202024-04-12 12:46:40 +08007895/**
7896 * Three windows:
7897 * - left window, which has FLAG_SLIPPERY, so it supports slippery exit
7898 * - right window
7899 * - spy window
7900 * The three windows do not overlap.
7901 *
7902 * We have two devices reporting events:
7903 * - Device A reports ACTION_DOWN, which lands in the left window
7904 * - Device B reports ACTION_DOWN, which lands in the spy window.
7905 * - Now, device B reports ACTION_MOVE events which move to the right window.
7906 *
7907 * The right window should not receive any events because the spy window is not a foreground window,
7908 * and also it does not support slippery touches.
7909 */
7910TEST_F(InputDispatcherTest, MultiDeviceSpyWindowSlipTest) {
7911 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7912 sp<FakeWindowHandle> leftWindow =
7913 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007914 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007915 leftWindow->setFrame(Rect(0, 0, 100, 100));
7916 leftWindow->setSlippery(true);
7917
7918 sp<FakeWindowHandle> rightWindow =
7919 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007920 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007921 rightWindow->setFrame(Rect(100, 0, 200, 100));
7922
7923 sp<FakeWindowHandle> spyWindow =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007924 sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
7925 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007926 spyWindow->setFrame(Rect(200, 0, 300, 100));
7927 spyWindow->setSpy(true);
7928 spyWindow->setTrustedOverlay(true);
7929
7930 mDispatcher->onWindowInfosChanged(
7931 {{*leftWindow->getInfo(), *rightWindow->getInfo(), *spyWindow->getInfo()}, {}, 0, 0});
7932
7933 const DeviceId deviceA = 9;
7934 const DeviceId deviceB = 3;
7935
7936 // Tap on left window with device A
7937 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7938 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
7939 .deviceId(deviceA)
7940 .build());
7941 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
7942
7943 // Tap on spy window with device B
7944 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
7945 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
7946 .deviceId(deviceB)
7947 .build());
7948 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
7949
7950 // Move to right window with device B. Touches should not slip to the right window, because spy
7951 // window is not a foreground window, and it does not have FLAG_SLIPPERY
7952 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
7953 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
7954 .deviceId(deviceB)
7955 .build());
7956 leftWindow->assertNoEvents();
7957 rightWindow->assertNoEvents();
7958 spyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
7959}
7960
7961/**
7962 * Three windows arranged horizontally and without any overlap.
7963 * The left and right windows have FLAG_SLIPPERY. The middle window does not have any special flags.
7964 *
7965 * We have two devices reporting events:
7966 * - Device A reports ACTION_DOWN which lands in the left window
7967 * - Device B reports ACTION_DOWN which lands in the right window
7968 * - Device B reports ACTION_MOVE that shifts to the middle window.
7969 * This should cause touches for Device B to slip from the right window to the middle window.
7970 * The right window should receive ACTION_CANCEL for device B and the
7971 * middle window should receive down event for Device B.
7972 * If device B reports more ACTION_MOVE events, the middle window should receive remaining events.
7973 */
7974TEST_F(InputDispatcherTest, MultiDeviceSlipperyWindowTest) {
Siarhei Vishniakoudd56df12024-05-20 14:56:38 -07007975 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
Linnan Li49b2b202024-04-12 12:46:40 +08007976 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
7977 sp<FakeWindowHandle> leftWindow =
7978 sp<FakeWindowHandle>::make(application, mDispatcher, "Left window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007979 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007980 leftWindow->setFrame(Rect(0, 0, 100, 100));
7981 leftWindow->setSlippery(true);
7982
7983 sp<FakeWindowHandle> middleWindow =
7984 sp<FakeWindowHandle>::make(application, mDispatcher, "middle window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007985 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007986 middleWindow->setFrame(Rect(100, 0, 200, 100));
7987
7988 sp<FakeWindowHandle> rightWindow =
7989 sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07007990 ui::LogicalDisplayId::DEFAULT);
Linnan Li49b2b202024-04-12 12:46:40 +08007991 rightWindow->setFrame(Rect(200, 0, 300, 100));
7992 rightWindow->setSlippery(true);
7993
7994 mDispatcher->onWindowInfosChanged(
7995 {{*leftWindow->getInfo(), *middleWindow->getInfo(), *rightWindow->getInfo()},
7996 {},
7997 0,
7998 0});
7999
8000 const DeviceId deviceA = 9;
8001 const DeviceId deviceB = 3;
8002
8003 // Tap on left window with device A
8004 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8005 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8006 .deviceId(deviceA)
8007 .build());
8008 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8009
8010 // Tap on right window with device B
8011 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8012 .pointer(PointerBuilder(0, ToolType::FINGER).x(250).y(50))
8013 .deviceId(deviceB)
8014 .build());
8015 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8016
8017 // Move to middle window with device B. Touches should slip to middle window, because right
8018 // window is a foreground window that's associated with device B and has FLAG_SLIPPERY.
8019 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8020 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8021 .deviceId(deviceB)
8022 .build());
8023 rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceB)));
8024 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
8025
8026 // Move to middle window with device A. Touches should slip to middle window, because left
8027 // window is a foreground window that's associated with device A and has FLAG_SLIPPERY.
8028 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8029 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
8030 .deviceId(deviceA)
8031 .build());
8032 leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(deviceA)));
8033 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8034
8035 // Ensure that middle window can receive the remaining move events.
8036 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8037 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
8038 .deviceId(deviceB)
8039 .build());
8040 leftWindow->assertNoEvents();
8041 middleWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceB)));
8042 rightWindow->assertNoEvents();
8043}
8044
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008045TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithMotions) {
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008046 using Uid = gui::Uid;
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008047 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8048
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008049 sp<FakeWindowHandle> leftWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Left",
8050 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008051 leftWindow->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008052 leftWindow->setOwnerInfo(gui::Pid{1}, Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008053
8054 sp<FakeWindowHandle> rightSpy =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008055 sp<FakeWindowHandle>::make(application, mDispatcher, "Right spy",
8056 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008057 rightSpy->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008058 rightSpy->setOwnerInfo(gui::Pid{2}, Uid{102});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008059 rightSpy->setSpy(true);
8060 rightSpy->setTrustedOverlay(true);
8061
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008062 sp<FakeWindowHandle> rightWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Right",
8063 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008064 rightWindow->setFrame(Rect(100, 0, 200, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008065 rightWindow->setOwnerInfo(gui::Pid{3}, Uid{103});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008066
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008067 mDispatcher->onWindowInfosChanged(
8068 {{*rightSpy->getInfo(), *rightWindow->getInfo(), *leftWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008069
8070 // Touch in the left window
8071 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8072 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8073 .build());
8074 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionDown());
8075 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008076 ASSERT_NO_FATAL_FAILURE(
8077 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008078
8079 // Touch another finger over the right windows
8080 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8081 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8082 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8083 .build());
8084 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionDown());
8085 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionDown());
8086 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionMove());
8087 mDispatcher->waitForIdle();
8088 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008089 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID,
8090 {Uid{101}, Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008091
8092 // Release finger over left window. The UP actions are not treated as device interaction.
8093 // The windows that did not receive the UP pointer will receive MOVE events, but since this
8094 // is part of the UP action, we do not treat this as device interaction.
8095 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_0_UP, AINPUT_SOURCE_TOUCHSCREEN)
8096 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8097 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8098 .build());
8099 ASSERT_NO_FATAL_FAILURE(leftWindow->consumeMotionUp());
8100 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8101 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8102 mDispatcher->waitForIdle();
8103 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8104
8105 // Move remaining finger
8106 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
8107 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8108 .build());
8109 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionMove());
8110 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionMove());
8111 mDispatcher->waitForIdle();
8112 ASSERT_NO_FATAL_FAILURE(
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008113 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {Uid{102}, Uid{103}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008114
8115 // Release all fingers
8116 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
8117 .pointer(PointerBuilder(1, ToolType::FINGER).x(150).y(50))
8118 .build());
8119 ASSERT_NO_FATAL_FAILURE(rightSpy->consumeMotionUp());
8120 ASSERT_NO_FATAL_FAILURE(rightWindow->consumeMotionUp());
8121 mDispatcher->waitForIdle();
8122 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8123}
8124
8125TEST_F(InputDispatcherTest, NotifiesDeviceInteractionsWithKeys) {
8126 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8127
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008128 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8129 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008130 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +00008131 window->setOwnerInfo(gui::Pid{1}, gui::Uid{101});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008132
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008133 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008134 setFocusedWindow(window);
8135 ASSERT_NO_FATAL_FAILURE(window->consumeFocusEvent(true));
8136
8137 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008138 ASSERT_NO_FATAL_FAILURE(window->consumeKeyDown(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008139 mDispatcher->waitForIdle();
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +00008140 ASSERT_NO_FATAL_FAILURE(
8141 mFakePolicy->assertNotifyDeviceInteractionWasCalled(DEVICE_ID, {gui::Uid{101}}));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008142
8143 // The UP actions are not treated as device interaction.
8144 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008145 ASSERT_NO_FATAL_FAILURE(window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan8ede1d12023-05-08 19:37:44 +00008146 mDispatcher->waitForIdle();
8147 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyDeviceInteractionWasNotCalled());
8148}
8149
Prabir Pradhan5893d362023-11-17 04:30:40 +00008150TEST_F(InputDispatcherTest, HoverEnterExitSynthesisUsesNewEventId) {
8151 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
8152
8153 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008154 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008155 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008156 sp<FakeWindowHandle> right =
8157 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
8158 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008159 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008160 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
8161 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008162 spy->setFrame(Rect(0, 0, 200, 100));
8163 spy->setTrustedOverlay(true);
8164 spy->setSpy(true);
8165
8166 mDispatcher->onWindowInfosChanged(
8167 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
8168
8169 // Send hover move to the left window, and ensure hover enter is synthesized with a new eventId.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008170 NotifyMotionArgs notifyArgs =
8171 generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8172 ui::LogicalDisplayId::DEFAULT, {PointF{50, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008173 mDispatcher->notifyMotion(notifyArgs);
8174
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008175 std::unique_ptr<MotionEvent> leftEnter = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008176 AllOf(WithMotionAction(ACTION_HOVER_ENTER), Not(WithEventId(notifyArgs.id)),
8177 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008178 ASSERT_NE(nullptr, leftEnter);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008179 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8180 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008181 Not(WithEventId(leftEnter->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008182 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8183
8184 // Send move to the right window, and ensure hover exit and enter are synthesized with new ids.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008185 notifyArgs = generateMotionArgs(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS,
8186 ui::LogicalDisplayId::DEFAULT, {PointF{150, 50}});
Prabir Pradhan5893d362023-11-17 04:30:40 +00008187 mDispatcher->notifyMotion(notifyArgs);
8188
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008189 std::unique_ptr<MotionEvent> leftExit = left->consumeMotionEvent(
Prabir Pradhan5893d362023-11-17 04:30:40 +00008190 AllOf(WithMotionAction(ACTION_HOVER_EXIT), Not(WithEventId(notifyArgs.id)),
8191 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008192 ASSERT_NE(nullptr, leftExit);
Prabir Pradhan5893d362023-11-17 04:30:40 +00008193 right->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER),
8194 Not(WithEventId(notifyArgs.id)),
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008195 Not(WithEventId(leftExit->getId())),
Prabir Pradhan5893d362023-11-17 04:30:40 +00008196 WithEventIdSource(IdGenerator::Source::INPUT_DISPATCHER)));
8197
8198 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithEventId(notifyArgs.id)));
8199}
8200
Linnan Liccf6ce32024-04-11 20:32:13 +08008201/**
8202 * When a device reports a DOWN event, which lands in a window that supports splits, and then the
8203 * device then reports a POINTER_DOWN, which lands in the location of a non-existing window, then
8204 * the previous window should receive this event and not be dropped.
8205 */
8206TEST_F(InputDispatcherMultiDeviceTest, SingleDevicePointerDownEventRetentionWithoutWindowTarget) {
8207 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008208 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8209 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008210 window->setFrame(Rect(0, 0, 100, 100));
8211 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8212
8213 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8214 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8215 .build());
8216
8217 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN)));
8218
8219 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8220 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8221 .pointer(PointerBuilder(1, ToolType::FINGER).x(200).y(200))
8222 .build());
8223
8224 window->consumeMotionEvent(AllOf(WithMotionAction(POINTER_1_DOWN)));
8225}
8226
8227/**
8228 * When deviceA reports a DOWN event, which lands in a window that supports splits, and then deviceB
8229 * also reports a DOWN event, which lands in the location of a non-existing window, then the
8230 * previous window should receive deviceB's event and it should be dropped.
8231 */
8232TEST_F(InputDispatcherMultiDeviceTest, SecondDeviceDownEventDroppedWithoutWindowTarget) {
8233 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008234 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
8235 ui::LogicalDisplayId::DEFAULT);
Linnan Liccf6ce32024-04-11 20:32:13 +08008236 window->setFrame(Rect(0, 0, 100, 100));
8237 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
8238
8239 const DeviceId deviceA = 9;
8240 const DeviceId deviceB = 3;
8241
8242 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8243 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
8244 .deviceId(deviceA)
8245 .build());
8246 window->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
8247
8248 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
8249 .pointer(PointerBuilder(0, ToolType::FINGER).x(200).y(200))
8250 .deviceId(deviceB)
8251 .build());
8252 window->assertNoEvents();
8253}
8254
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008255class InputDispatcherFallbackKeyTest : public InputDispatcherTest {
8256protected:
8257 std::shared_ptr<FakeApplicationHandle> mApp;
8258 sp<FakeWindowHandle> mWindow;
8259
8260 virtual void SetUp() override {
8261 InputDispatcherTest::SetUp();
8262
8263 mApp = std::make_shared<FakeApplicationHandle>();
8264
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008265 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Window",
8266 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008267 mWindow->setFrame(Rect(0, 0, 100, 100));
8268
8269 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
8270 setFocusedWindow(mWindow);
8271 ASSERT_NO_FATAL_FAILURE(mWindow->consumeFocusEvent(/*hasFocus=*/true));
8272 }
8273
8274 void setFallback(int32_t keycode) {
8275 mFakePolicy->setUnhandledKeyHandler([keycode](const KeyEvent& event) {
8276 return KeyEventBuilder(event).keyCode(keycode).build();
8277 });
8278 }
8279
8280 void consumeKey(bool handled, const ::testing::Matcher<KeyEvent>& matcher) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008281 std::unique_ptr<KeyEvent> event = mWindow->consumeKey(handled);
8282 ASSERT_NE(nullptr, event);
8283 ASSERT_THAT(*event, matcher);
Prabir Pradhanb0dad3a2023-11-02 20:52:47 +00008284 }
8285};
8286
8287TEST_F(InputDispatcherFallbackKeyTest, PolicyNotNotifiedForHandledKey) {
8288 mDispatcher->notifyKey(
8289 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8290 consumeKey(/*handled=*/true, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8291 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8292}
8293
8294TEST_F(InputDispatcherFallbackKeyTest, PolicyNotifiedForUnhandledKey) {
8295 mDispatcher->notifyKey(
8296 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8297 consumeKey(/*handled=*/false, AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A)));
8298 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8299}
8300
8301TEST_F(InputDispatcherFallbackKeyTest, NoFallbackRequestedByPolicy) {
8302 mDispatcher->notifyKey(
8303 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8304
8305 // Do not handle this key event.
8306 consumeKey(/*handled=*/false,
8307 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8308 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8309
8310 // Since the policy did not request any fallback to be generated, ensure there are no events.
8311 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8312}
8313
8314TEST_F(InputDispatcherFallbackKeyTest, FallbackDispatchForUnhandledKey) {
8315 setFallback(AKEYCODE_B);
8316 mDispatcher->notifyKey(
8317 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8318
8319 // Do not handle this key event.
8320 consumeKey(/*handled=*/false,
8321 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8322
8323 // Since the key was not handled, ensure the fallback event was dispatched instead.
8324 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8325 consumeKey(/*handled=*/true,
8326 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8327 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8328
8329 // Release the original key, and ensure the fallback key is also released.
8330 mDispatcher->notifyKey(
8331 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8332 consumeKey(/*handled=*/false,
8333 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8334 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8335 consumeKey(/*handled=*/true,
8336 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8337 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8338
8339 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8340 mWindow->assertNoEvents();
8341}
8342
8343TEST_F(InputDispatcherFallbackKeyTest, AppHandlesPreviouslyUnhandledKey) {
8344 setFallback(AKEYCODE_B);
8345 mDispatcher->notifyKey(
8346 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8347
8348 // Do not handle this key event, but handle the fallback.
8349 consumeKey(/*handled=*/false,
8350 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8351 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8352 consumeKey(/*handled=*/true,
8353 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8354 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8355
8356 // Release the original key, and ensure the fallback key is also released.
8357 mDispatcher->notifyKey(
8358 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8359 // But this time, the app handles the original key.
8360 consumeKey(/*handled=*/true,
8361 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8362 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8363 // Ensure the fallback key is canceled.
8364 consumeKey(/*handled=*/true,
8365 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8366 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8367
8368 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8369 mWindow->assertNoEvents();
8370}
8371
8372TEST_F(InputDispatcherFallbackKeyTest, AppDoesNotHandleFallback) {
8373 setFallback(AKEYCODE_B);
8374 mDispatcher->notifyKey(
8375 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8376
8377 // Do not handle this key event.
8378 consumeKey(/*handled=*/false,
8379 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8380 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8381 // App does not handle the fallback either, so ensure another fallback is not generated.
8382 setFallback(AKEYCODE_C);
8383 consumeKey(/*handled=*/false,
8384 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8385 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8386
8387 // Release the original key, and ensure the fallback key is also released.
8388 setFallback(AKEYCODE_B);
8389 mDispatcher->notifyKey(
8390 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8391 consumeKey(/*handled=*/false,
8392 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8393 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8394 consumeKey(/*handled=*/false,
8395 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8396 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8397
8398 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8399 mWindow->assertNoEvents();
8400}
8401
8402TEST_F(InputDispatcherFallbackKeyTest, InconsistentPolicyCancelsFallback) {
8403 setFallback(AKEYCODE_B);
8404 mDispatcher->notifyKey(
8405 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8406
8407 // Do not handle this key event, so fallback is generated.
8408 consumeKey(/*handled=*/false,
8409 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8410 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8411 consumeKey(/*handled=*/true,
8412 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8413 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8414
8415 // Release the original key, but assume the policy is misbehaving and it
8416 // generates an inconsistent fallback to the one from the DOWN event.
8417 setFallback(AKEYCODE_C);
8418 mDispatcher->notifyKey(
8419 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8420 consumeKey(/*handled=*/false,
8421 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8422 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8423 // Ensure the fallback key reported before as DOWN is canceled due to the inconsistency.
8424 consumeKey(/*handled=*/true,
8425 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8426 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8427
8428 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8429 mWindow->assertNoEvents();
8430}
8431
8432TEST_F(InputDispatcherFallbackKeyTest, CanceledKeyCancelsFallback) {
8433 setFallback(AKEYCODE_B);
8434 mDispatcher->notifyKey(
8435 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8436
8437 // Do not handle this key event, so fallback is generated.
8438 consumeKey(/*handled=*/false,
8439 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8440 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8441 consumeKey(/*handled=*/true,
8442 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8443 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8444
8445 // The original key is canceled.
8446 mDispatcher->notifyKey(KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD)
8447 .keyCode(AKEYCODE_A)
8448 .addFlag(AKEY_EVENT_FLAG_CANCELED)
8449 .build());
8450 consumeKey(/*handled=*/false,
8451 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8452 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8453 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8454 // Ensure the fallback key is also canceled due to the original key being canceled.
8455 consumeKey(/*handled=*/true,
8456 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8457 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8458
8459 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyNotReported());
8460 mWindow->assertNoEvents();
8461}
8462
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008463TEST_F(InputDispatcherFallbackKeyTest, InputChannelRemovedDuringPolicyCall) {
Prabir Pradhanb13da8f2024-01-09 23:10:13 +00008464 setFallback(AKEYCODE_B);
8465 mDispatcher->notifyKey(
8466 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8467
8468 // Do not handle this key event.
8469 consumeKey(/*handled=*/false,
8470 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8471 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8472 consumeKey(/*handled=*/true,
8473 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8474 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8475
8476 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8477 // When the unhandled key is reported to the policy next, remove the input channel.
8478 mDispatcher->removeInputChannel(mWindow->getToken());
8479 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8480 });
8481 // Release the original key, and let the app now handle the previously unhandled key.
8482 // This should result in the previously generated fallback key to be cancelled.
8483 // Since the policy was notified of the unhandled DOWN event earlier, it will also be notified
8484 // of the UP event for consistency. The Dispatcher calls into the policy from its own thread
8485 // without holding the lock, because it need to synchronously fetch the fallback key. While in
8486 // the policy call, we will now remove the input channel. Once the policy call returns, the
8487 // Dispatcher will no longer have a channel to send cancellation events to. Ensure this does
8488 // not cause any crashes.
8489 mDispatcher->notifyKey(
8490 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8491 consumeKey(/*handled=*/true,
8492 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8493 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8494}
8495
Prabir Pradhanfa2c69f2024-02-01 20:31:34 +00008496TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedDuringPolicyCall) {
8497 setFallback(AKEYCODE_B);
8498 mDispatcher->notifyKey(
8499 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8500
8501 // Do not handle this key event.
8502 consumeKey(/*handled=*/false,
8503 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8504 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8505 consumeKey(/*handled=*/true,
8506 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8507 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8508
8509 mFakePolicy->setUnhandledKeyHandler([&](const KeyEvent& event) {
8510 // When the unhandled key is reported to the policy next, remove the window.
8511 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8512 return KeyEventBuilder(event).keyCode(AKEYCODE_B).build();
8513 });
8514 // Release the original key, which the app will not handle. When this unhandled key is reported
8515 // to the policy, the window will be removed.
8516 mDispatcher->notifyKey(
8517 KeyArgsBuilder(ACTION_UP, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8518 consumeKey(/*handled=*/false,
8519 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8520 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8521
8522 // Since the window was removed, it loses focus, and the channel state will be reset.
8523 consumeKey(/*handled=*/true,
8524 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8525 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8526 mWindow->consumeFocusEvent(false);
8527 mWindow->assertNoEvents();
8528}
8529
8530TEST_F(InputDispatcherFallbackKeyTest, WindowRemovedWhileAwaitingFinishedSignal) {
8531 setFallback(AKEYCODE_B);
8532 mDispatcher->notifyKey(
8533 KeyArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_KEYBOARD).keyCode(AKEYCODE_A).build());
8534
8535 // Do not handle this key event.
8536 consumeKey(/*handled=*/false,
8537 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_A), WithFlags(0)));
8538 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertUnhandledKeyReported(AKEYCODE_A));
8539 const auto [seq, event] = mWindow->receiveEvent();
8540 ASSERT_TRUE(seq.has_value() && event != nullptr) << "Failed to receive fallback event";
8541 ASSERT_EQ(event->getType(), InputEventType::KEY);
8542 ASSERT_THAT(static_cast<const KeyEvent&>(*event),
8543 AllOf(WithKeyAction(ACTION_DOWN), WithKeyCode(AKEYCODE_B),
8544 WithFlags(AKEY_EVENT_FLAG_FALLBACK)));
8545
8546 // Remove the window now, which should generate a cancellations and make the window lose focus.
8547 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
8548 consumeKey(/*handled=*/true,
8549 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_A),
8550 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8551 consumeKey(/*handled=*/true,
8552 AllOf(WithKeyAction(ACTION_UP), WithKeyCode(AKEYCODE_B),
8553 WithFlags(AKEY_EVENT_FLAG_FALLBACK | AKEY_EVENT_FLAG_CANCELED)));
8554 mWindow->consumeFocusEvent(false);
8555
8556 // Finish the event by reporting it as handled.
8557 mWindow->finishEvent(*seq);
8558 mWindow->assertNoEvents();
8559}
8560
Garfield Tan1c7bc862020-01-28 13:24:04 -08008561class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
8562protected:
Siarhei Vishniakoufa2a0492023-11-14 13:13:18 -08008563 static constexpr std::chrono::nanoseconds KEY_REPEAT_TIMEOUT = 40ms;
8564 static constexpr std::chrono::nanoseconds KEY_REPEAT_DELAY = 40ms;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008565
Chris Yea209fde2020-07-22 13:54:51 -07008566 std::shared_ptr<FakeApplicationHandle> mApp;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008567 sp<FakeWindowHandle> mWindow;
8568
8569 virtual void SetUp() override {
Prabir Pradhandae52792023-12-15 07:36:40 +00008570 InputDispatcherTest::SetUp();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008571
Prabir Pradhandae52792023-12-15 07:36:40 +00008572 mDispatcher->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008573 setUpWindow();
8574 }
8575
8576 void setUpWindow() {
Chris Yea209fde2020-07-22 13:54:51 -07008577 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008578 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "Fake Window",
8579 ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008580
Vishnu Nair47074b82020-08-14 11:54:47 -07008581 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008582 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008583 setFocusedWindow(mWindow);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008584 mWindow->consumeFocusEvent(true);
8585 }
8586
Chris Ye2ad95392020-09-01 13:44:44 -07008587 void sendAndConsumeKeyDown(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008588 NotifyKeyArgs keyArgs =
8589 generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008590 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008591 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008592 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008593
8594 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008595 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008596 }
8597
8598 void expectKeyRepeatOnce(int32_t repeatCount) {
8599 SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008600 mWindow->consumeKeyEvent(
8601 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithRepeatCount(repeatCount)));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008602 }
8603
Chris Ye2ad95392020-09-01 13:44:44 -07008604 void sendAndConsumeKeyUp(int32_t deviceId) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008605 NotifyKeyArgs keyArgs =
8606 generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT);
Chris Ye2ad95392020-09-01 13:44:44 -07008607 keyArgs.deviceId = deviceId;
Garfield Tan1c7bc862020-01-28 13:24:04 -08008608 keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
Prabir Pradhan678438e2023-04-13 19:32:51 +00008609 mDispatcher->notifyKey(keyArgs);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008610
8611 // Window should receive key down event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008612 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
Harry Cutts33476232023-01-30 19:57:29 +00008613 /*expectedFlags=*/0);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008614 }
Hu Guofe3c8f12023-09-22 17:20:15 +08008615
8616 void injectKeyRepeat(int32_t repeatCount) {
8617 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008618 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, repeatCount,
8619 ui::LogicalDisplayId::DEFAULT))
Hu Guofe3c8f12023-09-22 17:20:15 +08008620 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
8621 }
Garfield Tan1c7bc862020-01-28 13:24:04 -08008622};
8623
8624TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
Harry Cutts33476232023-01-30 19:57:29 +00008625 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008626 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8627 expectKeyRepeatOnce(repeatCount);
8628 }
8629}
8630
8631TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeatFromTwoDevices) {
Harry Cutts33476232023-01-30 19:57:29 +00008632 sendAndConsumeKeyDown(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008633 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8634 expectKeyRepeatOnce(repeatCount);
8635 }
Harry Cutts33476232023-01-30 19:57:29 +00008636 sendAndConsumeKeyDown(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008637 /* repeatCount will start from 1 for deviceId 2 */
Garfield Tan1c7bc862020-01-28 13:24:04 -08008638 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
8639 expectKeyRepeatOnce(repeatCount);
8640 }
8641}
8642
8643TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008644 sendAndConsumeKeyDown(/*deviceId=*/1);
8645 expectKeyRepeatOnce(/*repeatCount=*/1);
8646 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008647 mWindow->assertNoEvents();
8648}
8649
8650TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatAfterStaleDeviceKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008651 sendAndConsumeKeyDown(/*deviceId=*/1);
8652 expectKeyRepeatOnce(/*repeatCount=*/1);
8653 sendAndConsumeKeyDown(/*deviceId=*/2);
8654 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008655 // Stale key up from device 1.
Harry Cutts33476232023-01-30 19:57:29 +00008656 sendAndConsumeKeyUp(/*deviceId=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008657 // Device 2 is still down, keep repeating
Harry Cutts33476232023-01-30 19:57:29 +00008658 expectKeyRepeatOnce(/*repeatCount=*/2);
8659 expectKeyRepeatOnce(/*repeatCount=*/3);
Chris Ye2ad95392020-09-01 13:44:44 -07008660 // Device 2 key up
Harry Cutts33476232023-01-30 19:57:29 +00008661 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008662 mWindow->assertNoEvents();
8663}
8664
8665TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_KeyRepeatStopsAfterRepeatingKeyUp) {
Harry Cutts33476232023-01-30 19:57:29 +00008666 sendAndConsumeKeyDown(/*deviceId=*/1);
8667 expectKeyRepeatOnce(/*repeatCount=*/1);
8668 sendAndConsumeKeyDown(/*deviceId=*/2);
8669 expectKeyRepeatOnce(/*repeatCount=*/1);
Chris Ye2ad95392020-09-01 13:44:44 -07008670 // Device 2 which holds the key repeating goes up, expect the repeating to stop.
Harry Cutts33476232023-01-30 19:57:29 +00008671 sendAndConsumeKeyUp(/*deviceId=*/2);
Chris Ye2ad95392020-09-01 13:44:44 -07008672 // Device 1 still holds key down, but the repeating was already stopped
Garfield Tan1c7bc862020-01-28 13:24:04 -08008673 mWindow->assertNoEvents();
8674}
8675
liushenxiang42232912021-05-21 20:24:09 +08008676TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
8677 sendAndConsumeKeyDown(DEVICE_ID);
Harry Cutts33476232023-01-30 19:57:29 +00008678 expectKeyRepeatOnce(/*repeatCount=*/1);
Prabir Pradhan678438e2023-04-13 19:32:51 +00008679 mDispatcher->notifyDeviceReset({/*id=*/10, /*eventTime=*/20, DEVICE_ID});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008680 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT,
liushenxiang42232912021-05-21 20:24:09 +08008681 AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
8682 mWindow->assertNoEvents();
8683}
8684
Garfield Tan1c7bc862020-01-28 13:24:04 -08008685TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008686 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008687 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008688 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008689 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8690 ASSERT_NE(nullptr, repeatEvent);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008691 EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008692 IdGenerator::getSource(repeatEvent->getId()));
Garfield Tan1c7bc862020-01-28 13:24:04 -08008693 }
8694}
8695
8696TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
Michael Wrighte1cbbd62023-02-22 19:32:13 +00008697 GTEST_SKIP() << "Flaky test (b/270393106)";
Harry Cutts33476232023-01-30 19:57:29 +00008698 sendAndConsumeKeyDown(/*deviceId=*/1);
Garfield Tan1c7bc862020-01-28 13:24:04 -08008699
8700 std::unordered_set<int32_t> idSet;
8701 for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08008702 std::unique_ptr<KeyEvent> repeatEvent = mWindow->consumeKey();
8703 ASSERT_NE(nullptr, repeatEvent);
8704 int32_t id = repeatEvent->getId();
Garfield Tan1c7bc862020-01-28 13:24:04 -08008705 EXPECT_EQ(idSet.end(), idSet.find(id));
8706 idSet.insert(id);
8707 }
8708}
8709
Hu Guofe3c8f12023-09-22 17:20:15 +08008710TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_CorrectRepeatCountWhenInjectKeyRepeat) {
8711 injectKeyRepeat(0);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008712 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Hu Guofe3c8f12023-09-22 17:20:15 +08008713 for (int32_t repeatCount = 1; repeatCount <= 2; ++repeatCount) {
8714 expectKeyRepeatOnce(repeatCount);
8715 }
8716 injectKeyRepeat(1);
8717 // Expect repeatCount to be 3 instead of 1
8718 expectKeyRepeatOnce(3);
8719}
8720
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008721/* Test InputDispatcher for MultiDisplay */
8722class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
8723public:
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008724 virtual void SetUp() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008725 InputDispatcherTest::SetUp();
Arthur Hungb92218b2018-08-14 12:00:21 +08008726
Chris Yea209fde2020-07-22 13:54:51 -07008727 application1 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008728 windowInPrimary = sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1",
8729 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008730
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008731 // Set focus window for primary display, but focused display would be second one.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008732 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application1);
Vishnu Nair47074b82020-08-14 11:54:47 -07008733 windowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008734 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
8735
Vishnu Nair958da932020-08-21 17:12:37 -07008736 setFocusedWindow(windowInPrimary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008737 windowInPrimary->consumeFocusEvent(true);
Arthur Hungb92218b2018-08-14 12:00:21 +08008738
Chris Yea209fde2020-07-22 13:54:51 -07008739 application2 = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008740 windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07008741 sp<FakeWindowHandle>::make(application2, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008742 // Set focus to second display window.
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008743 // Set focus display to second one.
8744 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +00008745 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
8746
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008747 // Set focus window for second display.
8748 mDispatcher->setFocusedApplication(SECOND_DISPLAY_ID, application2);
Vishnu Nair47074b82020-08-14 11:54:47 -07008749 windowInSecondary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008750 mDispatcher->onWindowInfosChanged(
8751 {{*windowInPrimary->getInfo(), *windowInSecondary->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008752 setFocusedWindow(windowInSecondary);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008753 windowInSecondary->consumeFocusEvent(true);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008754 }
8755
Prabir Pradhan3608aad2019-10-02 17:08:26 -07008756 virtual void TearDown() override {
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008757 InputDispatcherTest::TearDown();
8758
Chris Yea209fde2020-07-22 13:54:51 -07008759 application1.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008760 windowInPrimary.clear();
Chris Yea209fde2020-07-22 13:54:51 -07008761 application2.reset();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008762 windowInSecondary.clear();
8763 }
8764
8765protected:
Chris Yea209fde2020-07-22 13:54:51 -07008766 std::shared_ptr<FakeApplicationHandle> application1;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008767 sp<FakeWindowHandle> windowInPrimary;
Chris Yea209fde2020-07-22 13:54:51 -07008768 std::shared_ptr<FakeApplicationHandle> application2;
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008769 sp<FakeWindowHandle> windowInSecondary;
8770};
8771
8772TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayTouch) {
8773 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008774 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008775 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8776 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008777 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008778 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungb92218b2018-08-14 12:00:21 +08008779 windowInSecondary->assertNoEvents();
8780
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008781 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008782 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008783 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008784 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08008785 windowInPrimary->assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08008786 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hungb92218b2018-08-14 12:00:21 +08008787}
8788
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008789TEST_F(InputDispatcherFocusOnTwoDisplaysTest, SetInputWindow_MultiDisplayFocus) {
Tiger Huang721e26f2018-07-24 22:26:19 +08008790 // Test inject a key down with display id specified.
Prabir Pradhan93f342c2021-03-11 15:05:30 -08008791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008792 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008793 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008794 windowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Tiger Huang721e26f2018-07-24 22:26:19 +08008795 windowInSecondary->assertNoEvents();
8796
8797 // Test inject a key down without display id specified.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008798 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008799 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hungb92218b2018-08-14 12:00:21 +08008800 windowInPrimary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008801 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hungb92218b2018-08-14 12:00:21 +08008802
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08008803 // Remove all windows in secondary display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008804 mDispatcher->onWindowInfosChanged({{*windowInPrimary->getInfo()}, {}, 0, 0});
Arthur Hungb92218b2018-08-14 12:00:21 +08008805
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008806 // Old focus should receive a cancel event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008807 windowInSecondary->consumeKeyUp(ui::LogicalDisplayId::INVALID, AKEY_EVENT_FLAG_CANCELED);
Arthur Hungb92218b2018-08-14 12:00:21 +08008808
8809 // Test inject a key down, should timeout because of no target window.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008810 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Arthur Hungb92218b2018-08-14 12:00:21 +08008811 windowInPrimary->assertNoEvents();
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01008812 windowInSecondary->consumeFocusEvent(false);
Arthur Hungb92218b2018-08-14 12:00:21 +08008813 windowInSecondary->assertNoEvents();
8814}
8815
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008816// Test per-display input monitors for motion event.
8817TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorMotionEvent_MultiDisplay) {
chaviwd1c23182019-12-20 18:44:56 -08008818 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008819 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08008820 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008821 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008822
8823 // Test touch down on primary display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008824 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008825 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8826 ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008827 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008828 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
8829 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008830 windowInSecondary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008831 monitorInSecondary.assertNoEvents();
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008832
8833 // Test touch down on second display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008834 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008835 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008836 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008837 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008838 monitorInPrimary.assertNoEvents();
Siarhei Vishniakouc5ca85c2019-11-15 17:20:00 -08008839 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
chaviwd1c23182019-12-20 18:44:56 -08008840 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008841
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08008842 // Lift up the touch from the second display
8843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008844 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Siarhei Vishniakou92c8fd52023-01-29 14:57:43 -08008845 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8846 windowInSecondary->consumeMotionUp(SECOND_DISPLAY_ID);
8847 monitorInSecondary.consumeMotionUp(SECOND_DISPLAY_ID);
8848
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008849 // Test inject a non-pointer motion event.
8850 // If specific a display, it will dispatch to the focused window of particular display,
8851 // or it will dispatch to the focused window of focused display.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008852 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008853 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL,
8854 ui::LogicalDisplayId::INVALID))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008855 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008856 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008857 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008858 windowInSecondary->consumeMotionDown(ui::LogicalDisplayId::INVALID);
8859 monitorInSecondary.consumeMotionDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008860}
8861
8862// Test per-display input monitors for key event.
8863TEST_F(InputDispatcherFocusOnTwoDisplaysTest, MonitorKeyEvent_MultiDisplay) {
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10008864 // Input monitor per display.
chaviwd1c23182019-12-20 18:44:56 -08008865 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008866 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
chaviwd1c23182019-12-20 18:44:56 -08008867 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008868 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008869
8870 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008871 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008872 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008873 windowInPrimary->assertNoEvents();
chaviwd1c23182019-12-20 18:44:56 -08008874 monitorInPrimary.assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008875 windowInSecondary->consumeKeyDown(ui::LogicalDisplayId::INVALID);
8876 monitorInSecondary.consumeKeyDown(ui::LogicalDisplayId::INVALID);
Arthur Hung2fbf37f2018-09-13 18:16:41 +08008877}
8878
Vishnu Nair958da932020-08-21 17:12:37 -07008879TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) {
8880 sp<FakeWindowHandle> secondWindowInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008881 sp<FakeWindowHandle>::make(application1, mDispatcher, "D_1_W2",
8882 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008883 secondWindowInPrimary->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07008884 mDispatcher->onWindowInfosChanged(
8885 {{*windowInPrimary->getInfo(), *secondWindowInPrimary->getInfo(),
8886 *windowInSecondary->getInfo()},
8887 {},
8888 0,
8889 0});
Vishnu Nair958da932020-08-21 17:12:37 -07008890 setFocusedWindow(secondWindowInPrimary);
8891 windowInPrimary->consumeFocusEvent(false);
8892 secondWindowInPrimary->consumeFocusEvent(true);
8893
8894 // Test inject a key down.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008896 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08008897 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Vishnu Nair958da932020-08-21 17:12:37 -07008898 windowInPrimary->assertNoEvents();
8899 windowInSecondary->assertNoEvents();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008900 secondWindowInPrimary->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -07008901}
8902
Arthur Hungdfd528e2021-12-08 13:23:04 +00008903TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) {
8904 FakeMonitorReceiver monitorInPrimary =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008905 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008906 FakeMonitorReceiver monitorInSecondary =
Prabir Pradhanfb549072023-10-05 19:17:36 +00008907 FakeMonitorReceiver(*mDispatcher, "M_2", SECOND_DISPLAY_ID);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008908
8909 // Test touch down on primary display.
8910 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008911 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
8912 ui::LogicalDisplayId::DEFAULT))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008913 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008914 windowInPrimary->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
8915 monitorInPrimary.consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008916
8917 // Test touch down on second display.
8918 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008919 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008920 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
8921 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID);
8922 monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID);
8923
8924 // Trigger cancel touch.
8925 mDispatcher->cancelCurrentTouch();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008926 windowInPrimary->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
8927 monitorInPrimary.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Arthur Hungdfd528e2021-12-08 13:23:04 +00008928 windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID);
8929 monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID);
8930
8931 // Test inject a move motion event, no window/monitor should receive the event.
8932 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008933 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008934 ui::LogicalDisplayId::DEFAULT, {110, 200}))
Arthur Hungdfd528e2021-12-08 13:23:04 +00008935 << "Inject motion event should return InputEventInjectionResult::FAILED";
8936 windowInPrimary->assertNoEvents();
8937 monitorInPrimary.assertNoEvents();
8938
8939 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07008940 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Arthur Hungdfd528e2021-12-08 13:23:04 +00008941 SECOND_DISPLAY_ID, {110, 200}))
8942 << "Inject motion event should return InputEventInjectionResult::FAILED";
8943 windowInSecondary->assertNoEvents();
8944 monitorInSecondary.assertNoEvents();
8945}
8946
Hu Guocb134f12023-12-23 13:42:44 +00008947/**
8948 * Send a key to the primary display and to the secondary display.
8949 * Then cause the key on the primary display to be canceled by sending in a stale key.
8950 * Ensure that the key on the primary display is canceled, and that the key on the secondary display
8951 * does not get canceled.
8952 */
8953TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture) {
8954 // Send a key down on primary display
8955 mDispatcher->notifyKey(
8956 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008957 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008958 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8959 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008960 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN),
8961 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00008962 windowInSecondary->assertNoEvents();
8963
8964 // Send a key down on second display
8965 mDispatcher->notifyKey(
8966 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
8967 .displayId(SECOND_DISPLAY_ID)
8968 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8969 .build());
8970 windowInSecondary->consumeKeyEvent(
8971 AllOf(WithKeyAction(AKEY_EVENT_ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
8972 windowInPrimary->assertNoEvents();
8973
8974 // Send a valid key up event on primary display that will be dropped because it is stale
8975 NotifyKeyArgs staleKeyUp =
8976 KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008977 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00008978 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
8979 .build();
8980 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
8981 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
8982 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
8983 mDispatcher->notifyKey(staleKeyUp);
8984
8985 // Only the key gesture corresponding to the dropped event should receive the cancel event.
8986 // Therefore, windowInPrimary should get the cancel event and windowInSecondary should not
8987 // receive any events.
8988 windowInPrimary->consumeKeyEvent(AllOf(WithKeyAction(AKEY_EVENT_ACTION_UP),
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07008989 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
Hu Guocb134f12023-12-23 13:42:44 +00008990 WithFlags(AKEY_EVENT_FLAG_CANCELED)));
8991 windowInSecondary->assertNoEvents();
8992}
8993
8994/**
8995 * Similar to 'WhenDropKeyEvent_OnlyCancelCorrespondingKeyGesture' but for motion events.
8996 */
8997TEST_F(InputDispatcherFocusOnTwoDisplaysTest, WhenDropMotionEvent_OnlyCancelCorrespondingGesture) {
8998 // Send touch down on primary display.
8999 mDispatcher->notifyMotion(
9000 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9001 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009002 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009003 .build());
9004 windowInPrimary->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009005 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Hu Guocb134f12023-12-23 13:42:44 +00009006 windowInSecondary->assertNoEvents();
9007
9008 // Send touch down on second display.
9009 mDispatcher->notifyMotion(
9010 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9011 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9012 .displayId(SECOND_DISPLAY_ID)
9013 .build());
9014 windowInPrimary->assertNoEvents();
9015 windowInSecondary->consumeMotionEvent(
9016 AllOf(WithMotionAction(ACTION_DOWN), WithDisplayId(SECOND_DISPLAY_ID)));
9017
9018 // inject a valid MotionEvent on primary display that will be stale when it arrives.
9019 NotifyMotionArgs staleMotionUp =
9020 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009021 .displayId(ui::LogicalDisplayId::DEFAULT)
Hu Guocb134f12023-12-23 13:42:44 +00009022 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
9023 .build();
9024 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 10ms;
9025 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
9026 std::this_thread::sleep_for(STALE_EVENT_TIMEOUT);
9027 mDispatcher->notifyMotion(staleMotionUp);
9028
9029 // For stale motion events, we let the gesture to complete. This behaviour is different from key
9030 // events, where we would cancel the current keys instead.
9031 windowInPrimary->consumeMotionEvent(WithMotionAction(ACTION_UP));
9032 windowInSecondary->assertNoEvents();
9033}
9034
Jackal Guof9696682018-10-05 12:23:23 +08009035class InputFilterTest : public InputDispatcherTest {
9036protected:
Linnan Li13bf76a2024-05-05 19:18:02 +08009037 void testNotifyMotion(ui::LogicalDisplayId displayId, bool expectToBeFiltered,
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009038 const ui::Transform& transform = ui::Transform()) {
Jackal Guof9696682018-10-05 12:23:23 +08009039 NotifyMotionArgs motionArgs;
9040
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009041 motionArgs =
9042 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009043 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009044 motionArgs =
9045 generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, displayId);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009046 mDispatcher->notifyMotion(motionArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009047 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08009048 if (expectToBeFiltered) {
Siarhei Vishniakou3218fc02023-06-15 20:41:02 -07009049 const auto xy = transform.transform(motionArgs.pointerCoords[0].getXYValue());
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009050 mFakePolicy->assertFilterInputEventWasCalled(motionArgs, xy);
Jackal Guof9696682018-10-05 12:23:23 +08009051 } else {
9052 mFakePolicy->assertFilterInputEventWasNotCalled();
9053 }
9054 }
9055
9056 void testNotifyKey(bool expectToBeFiltered) {
9057 NotifyKeyArgs keyArgs;
9058
9059 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009060 mDispatcher->notifyKey(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009061 keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP);
Prabir Pradhan678438e2023-04-13 19:32:51 +00009062 mDispatcher->notifyKey(keyArgs);
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009063 ASSERT_TRUE(mDispatcher->waitForIdle());
Jackal Guof9696682018-10-05 12:23:23 +08009064
9065 if (expectToBeFiltered) {
Siarhei Vishniakou8935a802019-11-15 16:41:44 -08009066 mFakePolicy->assertFilterInputEventWasCalled(keyArgs);
Jackal Guof9696682018-10-05 12:23:23 +08009067 } else {
9068 mFakePolicy->assertFilterInputEventWasNotCalled();
9069 }
9070 }
9071};
9072
9073// Test InputFilter for MotionEvent
9074TEST_F(InputFilterTest, MotionEvent_InputFilter) {
9075 // Since the InputFilter is disabled by default, check if touch events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009076 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009077 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009078
9079 // Enable InputFilter
9080 mDispatcher->setInputFilterEnabled(true);
9081 // Test touch on both primary and second display, and check if both events are filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009082 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009083 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009084
9085 // Disable InputFilter
9086 mDispatcher->setInputFilterEnabled(false);
9087 // Test touch on both primary and second display, and check if both events aren't filtered.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009088 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/false);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009089 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009090}
9091
9092// Test InputFilter for KeyEvent
9093TEST_F(InputFilterTest, KeyEvent_InputFilter) {
9094 // Since the InputFilter is disabled by default, check if key event aren't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009095 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009096
9097 // Enable InputFilter
9098 mDispatcher->setInputFilterEnabled(true);
9099 // Send a key event, and check if it is filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009100 testNotifyKey(/*expectToBeFiltered=*/true);
Jackal Guof9696682018-10-05 12:23:23 +08009101
9102 // Disable InputFilter
9103 mDispatcher->setInputFilterEnabled(false);
9104 // Send a key event, and check if it isn't filtered.
Harry Cutts101ee9b2023-07-06 18:04:14 +00009105 testNotifyKey(/*expectToBeFiltered=*/false);
Jackal Guof9696682018-10-05 12:23:23 +08009106}
9107
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009108// Ensure that MotionEvents sent to the InputFilter through InputListener are converted to the
9109// logical display coordinate space.
9110TEST_F(InputFilterTest, MotionEvent_UsesLogicalDisplayCoordinates_notifyMotion) {
9111 ui::Transform firstDisplayTransform;
9112 firstDisplayTransform.set({1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 0, 0, 1});
9113 ui::Transform secondDisplayTransform;
9114 secondDisplayTransform.set({-6.6, -5.5, -4.4, -3.3, -2.2, -1.1, 0, 0, 1});
9115
9116 std::vector<gui::DisplayInfo> displayInfos(2);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009117 displayInfos[0].displayId = ui::LogicalDisplayId::DEFAULT;
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009118 displayInfos[0].transform = firstDisplayTransform;
9119 displayInfos[1].displayId = SECOND_DISPLAY_ID;
9120 displayInfos[1].transform = secondDisplayTransform;
9121
Patrick Williamsd828f302023-04-28 17:52:08 -05009122 mDispatcher->onWindowInfosChanged({{}, displayInfos, 0, 0});
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009123
9124 // Enable InputFilter
9125 mDispatcher->setInputFilterEnabled(true);
9126
9127 // Ensure the correct transforms are used for the displays.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009128 testNotifyMotion(ui::LogicalDisplayId::DEFAULT, /*expectToBeFiltered=*/true,
9129 firstDisplayTransform);
Harry Cutts101ee9b2023-07-06 18:04:14 +00009130 testNotifyMotion(SECOND_DISPLAY_ID, /*expectToBeFiltered=*/true, secondDisplayTransform);
Prabir Pradhan81420cc2021-09-06 10:28:50 -07009131}
9132
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009133class InputFilterInjectionPolicyTest : public InputDispatcherTest {
9134protected:
9135 virtual void SetUp() override {
9136 InputDispatcherTest::SetUp();
9137
9138 /**
9139 * We don't need to enable input filter to test the injected event policy, but we enabled it
9140 * here to make the tests more realistic, since this policy only matters when inputfilter is
9141 * on.
9142 */
9143 mDispatcher->setInputFilterEnabled(true);
9144
9145 std::shared_ptr<InputApplicationHandle> application =
9146 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009147 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Test Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009148 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009149
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009150 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009151 mWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009152 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009153 setFocusedWindow(mWindow);
9154 mWindow->consumeFocusEvent(true);
9155 }
9156
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009157 void testInjectedKey(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9158 int32_t flags) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009159 KeyEvent event;
9160
9161 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9162 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_KEYBOARD,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009163 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0,
9164 AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime, eventTime);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009165 const int32_t additionalPolicyFlags =
9166 POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
9167 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009168 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009169 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009170 policyFlags | additionalPolicyFlags));
9171
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009172 mWindow->consumeKeyEvent(AllOf(WithDeviceId(resolvedDeviceId), WithFlags(flags)));
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009173 }
9174
9175 void testInjectedMotion(int32_t policyFlags, int32_t injectedDeviceId, int32_t resolvedDeviceId,
9176 int32_t flags) {
9177 MotionEvent event;
9178 PointerProperties pointerProperties[1];
9179 PointerCoords pointerCoords[1];
9180 pointerProperties[0].clear();
9181 pointerProperties[0].id = 0;
9182 pointerCoords[0].clear();
9183 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 300);
9184 pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 400);
9185
9186 ui::Transform identityTransform;
9187 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
9188 event.initialize(InputEvent::nextId(), injectedDeviceId, AINPUT_SOURCE_TOUCHSCREEN,
9189 DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
9190 AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
9191 identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
Prabir Pradhanb9b18502021-08-26 12:30:32 -07009192 AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
Evan Rosky09576692021-07-01 12:22:09 -07009193 eventTime,
Harry Cutts101ee9b2023-07-06 18:04:14 +00009194 /*pointerCount=*/1, pointerProperties, pointerCoords);
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009195
9196 const int32_t additionalPolicyFlags = POLICY_FLAG_PASS_TO_USER;
9197 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Harry Cutts33476232023-01-30 19:57:29 +00009198 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou4648fea2023-06-27 01:00:12 +00009199 InputEventInjectionSync::WAIT_FOR_RESULT, 100ms,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009200 policyFlags | additionalPolicyFlags));
9201
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009202 mWindow->consumeMotionEvent(AllOf(WithFlags(flags), WithDeviceId(resolvedDeviceId)));
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009203 }
9204
9205private:
9206 sp<FakeWindowHandle> mWindow;
9207};
9208
9209TEST_F(InputFilterInjectionPolicyTest, TrustedFilteredEvents_KeepOriginalDeviceId) {
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009210 // Must have POLICY_FLAG_FILTERED here to indicate that the event has gone through the input
9211 // filter. Without it, the event will no different from a regularly injected event, and the
9212 // injected device id will be overwritten.
Harry Cutts33476232023-01-30 19:57:29 +00009213 testInjectedKey(POLICY_FLAG_FILTERED, /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
9214 /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009215}
9216
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009217TEST_F(InputFilterInjectionPolicyTest, KeyEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009218 testInjectedKey(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009219 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009220 AKEY_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
9221}
9222
9223TEST_F(InputFilterInjectionPolicyTest,
9224 MotionEventsInjectedFromAccessibility_HaveAccessibilityFlag) {
9225 testInjectedMotion(POLICY_FLAG_FILTERED | POLICY_FLAG_INJECTED_FROM_ACCESSIBILITY,
Harry Cutts33476232023-01-30 19:57:29 +00009226 /*injectedDeviceId=*/3, /*resolvedDeviceId=*/3,
Siarhei Vishniakouf00a4ec2021-06-16 03:55:32 +00009227 AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009228}
9229
9230TEST_F(InputFilterInjectionPolicyTest, RegularInjectedEvents_ReceiveVirtualDeviceId) {
Harry Cutts33476232023-01-30 19:57:29 +00009231 testInjectedKey(/*policyFlags=*/0, /*injectedDeviceId=*/3,
9232 /*resolvedDeviceId=*/VIRTUAL_KEYBOARD_ID, /*flags=*/0);
Siarhei Vishniakou5d552c42021-05-21 05:02:22 +00009233}
9234
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009235class InputDispatcherUserActivityPokeTests : public InputDispatcherTest {
9236protected:
9237 virtual void SetUp() override {
9238 InputDispatcherTest::SetUp();
9239
9240 std::shared_ptr<FakeApplicationHandle> application =
9241 std::make_shared<FakeApplicationHandle>();
9242 application->setDispatchingTimeout(100ms);
9243 mWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009244 ui::LogicalDisplayId::DEFAULT);
Yeabkal Wubshit222d83d2024-01-24 18:00:09 +00009245 mWindow->setFrame(Rect(0, 0, 100, 100));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009246 mWindow->setDispatchingTimeout(100ms);
9247 mWindow->setFocusable(true);
9248
9249 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009250 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009251
9252 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
9253 setFocusedWindow(mWindow);
9254 mWindow->consumeFocusEvent(true);
9255 }
9256
Linnan Li13bf76a2024-05-05 19:18:02 +08009257 void notifyAndConsumeMotion(int32_t action, uint32_t source, ui::LogicalDisplayId displayId,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009258 nsecs_t eventTime) {
9259 mDispatcher->notifyMotion(MotionArgsBuilder(action, source)
9260 .displayId(displayId)
9261 .eventTime(eventTime)
9262 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9263 .build());
9264 mWindow->consumeMotionEvent(WithMotionAction(action));
9265 }
9266
9267private:
9268 sp<FakeWindowHandle> mWindow;
9269};
9270
9271TEST_F_WITH_FLAGS(
9272 InputDispatcherUserActivityPokeTests, MinPokeTimeObserved,
9273 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9274 rate_limit_user_activity_poke_in_dispatcher))) {
9275 mDispatcher->setMinTimeBetweenUserActivityPokes(50ms);
9276
9277 // First event of type TOUCH. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009278 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009279 milliseconds_to_nanoseconds(50));
9280 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009281 {{milliseconds_to_nanoseconds(50), USER_ACTIVITY_EVENT_TOUCH,
9282 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009283
9284 // 80ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009285 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009286 milliseconds_to_nanoseconds(130));
9287 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009288 {{milliseconds_to_nanoseconds(130), USER_ACTIVITY_EVENT_TOUCH,
9289 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009290
9291 // First event of type OTHER. Should poke (despite being within 50ns of previous TOUCH event).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009292 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9293 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(135));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009294 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009295 {{milliseconds_to_nanoseconds(135), USER_ACTIVITY_EVENT_OTHER,
9296 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009297
9298 // Within 50ns of previous TOUCH event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009299 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009300 milliseconds_to_nanoseconds(140));
9301 mFakePolicy->assertUserActivityNotPoked();
9302
9303 // Within 50ns of previous OTHER event. Should NOT poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009304 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9305 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(150));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009306 mFakePolicy->assertUserActivityNotPoked();
9307
9308 // Within 50ns of previous TOUCH event (which was at time 130). Should NOT poke.
9309 // Note that STYLUS is mapped to TOUCH user activity, since it's a pointer-type source.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009310 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009311 milliseconds_to_nanoseconds(160));
9312 mFakePolicy->assertUserActivityNotPoked();
9313
9314 // 65ns > 50ns has passed since previous OTHER event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009315 notifyAndConsumeMotion(ACTION_SCROLL, AINPUT_SOURCE_ROTARY_ENCODER,
9316 ui::LogicalDisplayId::DEFAULT, milliseconds_to_nanoseconds(200));
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009317 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009318 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_OTHER,
9319 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009320
9321 // 170ns > 50ns has passed since previous TOUCH event. Should poke.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009322 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_STYLUS, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009323 milliseconds_to_nanoseconds(300));
9324 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009325 {{milliseconds_to_nanoseconds(300), USER_ACTIVITY_EVENT_TOUCH,
9326 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009327
9328 // Assert that there's no more user activity poke event.
9329 mFakePolicy->assertUserActivityNotPoked();
9330}
9331
9332TEST_F_WITH_FLAGS(
9333 InputDispatcherUserActivityPokeTests, DefaultMinPokeTimeOf100MsUsed,
9334 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9335 rate_limit_user_activity_poke_in_dispatcher))) {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009336 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009337 milliseconds_to_nanoseconds(200));
9338 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009339 {{milliseconds_to_nanoseconds(200), USER_ACTIVITY_EVENT_TOUCH,
9340 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009341
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009342 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009343 milliseconds_to_nanoseconds(280));
9344 mFakePolicy->assertUserActivityNotPoked();
9345
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009346 notifyAndConsumeMotion(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009347 milliseconds_to_nanoseconds(340));
9348 mFakePolicy->assertUserActivityPoked(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009349 {{milliseconds_to_nanoseconds(340), USER_ACTIVITY_EVENT_TOUCH,
9350 ui::LogicalDisplayId::DEFAULT}});
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009351}
9352
9353TEST_F_WITH_FLAGS(
9354 InputDispatcherUserActivityPokeTests, ZeroMinPokeTimeDisablesRateLimiting,
9355 REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(com::android::input::flags,
9356 rate_limit_user_activity_poke_in_dispatcher))) {
9357 mDispatcher->setMinTimeBetweenUserActivityPokes(0ms);
9358
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009359 notifyAndConsumeMotion(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9360 20);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009361 mFakePolicy->assertUserActivityPoked();
9362
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009363 notifyAndConsumeMotion(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
9364 30);
Yeabkal Wubshitb8aadfa2024-01-17 17:03:42 -08009365 mFakePolicy->assertUserActivityPoked();
9366}
9367
chaviwfd6d3512019-03-25 13:23:49 -07009368class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009369 virtual void SetUp() override {
chaviwfd6d3512019-03-25 13:23:49 -07009370 InputDispatcherTest::SetUp();
9371
Chris Yea209fde2020-07-22 13:54:51 -07009372 std::shared_ptr<FakeApplicationHandle> application =
9373 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009374 mUnfocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Top",
9375 ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009376 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
chaviwfd6d3512019-03-25 13:23:49 -07009377
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009378 mFocusedWindow = sp<FakeWindowHandle>::make(application, mDispatcher, "Second",
9379 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009380 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
chaviwfd6d3512019-03-25 13:23:49 -07009381
9382 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009383 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair47074b82020-08-14 11:54:47 -07009384 mFocusedWindow->setFocusable(true);
chaviwfd6d3512019-03-25 13:23:49 -07009385
9386 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009387 mDispatcher->onWindowInfosChanged(
9388 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009389 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009390 mFocusedWindow->consumeFocusEvent(true);
chaviwfd6d3512019-03-25 13:23:49 -07009391 }
9392
Prabir Pradhan3608aad2019-10-02 17:08:26 -07009393 virtual void TearDown() override {
chaviwfd6d3512019-03-25 13:23:49 -07009394 InputDispatcherTest::TearDown();
9395
9396 mUnfocusedWindow.clear();
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009397 mFocusedWindow.clear();
chaviwfd6d3512019-03-25 13:23:49 -07009398 }
9399
9400protected:
9401 sp<FakeWindowHandle> mUnfocusedWindow;
Siarhei Vishniakoub9b15352019-11-26 13:19:26 -08009402 sp<FakeWindowHandle> mFocusedWindow;
Siarhei Vishniakoufb9fcda2020-05-04 14:59:19 -07009403 static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
chaviwfd6d3512019-03-25 13:23:49 -07009404};
9405
9406// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9407// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
9408// the onPointerDownOutsideFocus callback.
9409TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009410 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009411 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9412 ui::LogicalDisplayId::DEFAULT, {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009413 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009414 mUnfocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009415
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009416 ASSERT_TRUE(mDispatcher->waitForIdle());
chaviwfd6d3512019-03-25 13:23:49 -07009417 mFakePolicy->assertOnPointerDownEquals(mUnfocusedWindow->getToken());
9418}
9419
9420// Have two windows, one with focus. Inject MotionEvent with source TRACKBALL and action
9421// DOWN on the window that doesn't have focus. Ensure no window received the
9422// onPointerDownOutsideFocus callback.
9423TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009424 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009425 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TRACKBALL, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009426 {20, 20}))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009427 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009428 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009429
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009430 ASSERT_TRUE(mDispatcher->waitForIdle());
9431 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009432}
9433
9434// Have two windows, one with focus. Inject KeyEvent with action DOWN on the window that doesn't
9435// have focus. Ensure no window received the onPointerDownOutsideFocus callback.
9436TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonMotionFailure) {
Prabir Pradhan93f342c2021-03-11 15:05:30 -08009437 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009438 injectKeyDownNoRepeat(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009439 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009440 mFocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
chaviwfd6d3512019-03-25 13:23:49 -07009441
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009442 ASSERT_TRUE(mDispatcher->waitForIdle());
9443 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009444}
9445
9446// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
9447// DOWN on the window that already has focus. Ensure no window received the
9448// onPointerDownOutsideFocus callback.
Siarhei Vishniakou870ecec2020-12-09 08:07:46 -10009449TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009450 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009451 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9452 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_TOUCH_POINT))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009453 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakou03aee2a2020-04-13 20:44:54 -07009454 mFocusedWindow->consumeMotionDown();
chaviwfd6d3512019-03-25 13:23:49 -07009455
Siarhei Vishniakou2bfa9052019-11-21 18:10:54 -08009456 ASSERT_TRUE(mDispatcher->waitForIdle());
9457 mFakePolicy->assertOnPointerDownWasNotCalled();
chaviwfd6d3512019-03-25 13:23:49 -07009458}
9459
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009460// Have two windows, one with focus. Injecting a trusted DOWN MotionEvent with the flag
9461// NO_FOCUS_CHANGE on the unfocused window should not call the onPointerDownOutsideFocus callback.
9462TEST_F(InputDispatcherOnPointerDownOutsideFocus, NoFocusChangeFlag) {
9463 const MotionEvent event =
9464 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_MOUSE)
9465 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -07009466 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(20).y(20))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009467 .addFlag(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)
9468 .build();
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009469 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionEvent(*mDispatcher, event))
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009470 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009471 mUnfocusedWindow->consumeAnyMotionDown(ui::LogicalDisplayId::DEFAULT,
9472 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Prabir Pradhan47cf0a02021-03-11 20:30:57 -08009473
9474 ASSERT_TRUE(mDispatcher->waitForIdle());
9475 mFakePolicy->assertOnPointerDownWasNotCalled();
9476 // Ensure that the unfocused window did not receive any FOCUS events.
9477 mUnfocusedWindow->assertNoEvents();
9478}
9479
chaviwaf87b3e2019-10-01 16:59:28 -07009480// These tests ensures we can send touch events to a single client when there are multiple input
9481// windows that point to the same client token.
9482class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest {
9483 virtual void SetUp() override {
9484 InputDispatcherTest::SetUp();
9485
Chris Yea209fde2020-07-22 13:54:51 -07009486 std::shared_ptr<FakeApplicationHandle> application =
9487 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009488 mWindow1 = sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window 1",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009489 ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009490 mWindow1->setFrame(Rect(0, 0, 100, 100));
9491
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009492 mWindow2 = mWindow1->clone(ui::LogicalDisplayId::DEFAULT);
chaviwaf87b3e2019-10-01 16:59:28 -07009493 mWindow2->setFrame(Rect(100, 100, 200, 200));
9494
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009495 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009496 }
9497
9498protected:
9499 sp<FakeWindowHandle> mWindow1;
9500 sp<FakeWindowHandle> mWindow2;
9501
9502 // Helper function to convert the point from screen coordinates into the window's space
chaviw3277faf2021-05-19 16:45:23 -05009503 static PointF getPointInWindow(const WindowInfo* windowInfo, const PointF& point) {
chaviw1ff3d1e2020-07-01 15:53:47 -07009504 vec2 vals = windowInfo->transform.transform(point.x, point.y);
9505 return {vals.x, vals.y};
chaviwaf87b3e2019-10-01 16:59:28 -07009506 }
9507
9508 void consumeMotionEvent(const sp<FakeWindowHandle>& window, int32_t expectedAction,
9509 const std::vector<PointF>& points) {
Siarhei Vishniakouf1035d42019-09-20 16:32:01 +01009510 const std::string name = window->getName();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009511 std::unique_ptr<MotionEvent> motionEvent =
Prabir Pradhan7662a8d2023-12-15 01:58:14 +00009512 window->consumeMotionEvent(WithMotionAction(expectedAction));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009513 ASSERT_NE(nullptr, motionEvent);
9514 ASSERT_EQ(points.size(), motionEvent->getPointerCount());
chaviwaf87b3e2019-10-01 16:59:28 -07009515
9516 for (size_t i = 0; i < points.size(); i++) {
9517 float expectedX = points[i].x;
9518 float expectedY = points[i].y;
9519
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009520 EXPECT_EQ(expectedX, motionEvent->getX(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009521 << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009522 << ", got " << motionEvent->getX(i);
9523 EXPECT_EQ(expectedY, motionEvent->getY(i))
chaviwaf87b3e2019-10-01 16:59:28 -07009524 << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str()
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009525 << ", got " << motionEvent->getY(i);
chaviwaf87b3e2019-10-01 16:59:28 -07009526 }
9527 }
chaviw9eaa22c2020-07-01 16:21:27 -07009528
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009529 void touchAndAssertPositions(sp<FakeWindowHandle> touchedWindow, int32_t action,
9530 const std::vector<PointF>& touchedPoints,
chaviw9eaa22c2020-07-01 16:21:27 -07009531 std::vector<PointF> expectedPoints) {
Prabir Pradhan678438e2023-04-13 19:32:51 +00009532 mDispatcher->notifyMotion(generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009533 ui::LogicalDisplayId::DEFAULT, touchedPoints));
chaviw9eaa22c2020-07-01 16:21:27 -07009534
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009535 consumeMotionEvent(touchedWindow, action, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009536 }
chaviwaf87b3e2019-10-01 16:59:28 -07009537};
9538
9539TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) {
9540 // Touch Window 1
9541 PointF touchedPoint = {10, 10};
9542 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009543 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009544
9545 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009546 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009547
9548 // Touch Window 2
9549 touchedPoint = {150, 150};
9550 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009551 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009552}
9553
chaviw9eaa22c2020-07-01 16:21:27 -07009554TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentTransform) {
9555 // Set scale value for window2
chaviwaf87b3e2019-10-01 16:59:28 -07009556 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009557 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviwaf87b3e2019-10-01 16:59:28 -07009558
9559 // Touch Window 1
9560 PointF touchedPoint = {10, 10};
9561 PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009562 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009563 // Release touch on Window 1
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009564 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009565
9566 // Touch Window 2
9567 touchedPoint = {150, 150};
9568 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009569 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
9570 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_UP, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009571
chaviw9eaa22c2020-07-01 16:21:27 -07009572 // Update the transform so rotation is set
9573 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009574 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009575 expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint);
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009576 touchAndAssertPositions(mWindow2, AMOTION_EVENT_ACTION_DOWN, {touchedPoint}, {expectedPoint});
chaviwaf87b3e2019-10-01 16:59:28 -07009577}
9578
chaviw9eaa22c2020-07-01 16:21:27 -07009579TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009580 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009581 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009582
9583 // Touch Window 1
9584 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9585 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009586 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009587
9588 // Touch Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009589 // Since this is part of the same touch gesture that has already been dispatched to Window 1,
9590 // the touch stream from Window 2 will be merged with the stream in Window 1. The merged stream
9591 // will continue to be dispatched through Window 1.
chaviw9eaa22c2020-07-01 16:21:27 -07009592 touchedPoints.push_back(PointF{150, 150});
9593 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009594 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009595
chaviw9eaa22c2020-07-01 16:21:27 -07009596 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009597 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009598 expectedPoints.pop_back();
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009599
chaviw9eaa22c2020-07-01 16:21:27 -07009600 // Update the transform so rotation is set for Window 2
9601 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009602 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009603 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009604 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009605}
9606
chaviw9eaa22c2020-07-01 16:21:27 -07009607TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleTouchMoveDifferentTransform) {
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009608 mWindow2->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009609 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009610
9611 // Touch Window 1
9612 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9613 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009614 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009615
9616 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009617 touchedPoints.push_back(PointF{150, 150});
9618 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009619
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009620 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009621
9622 // Move both windows
9623 touchedPoints = {{20, 20}, {175, 175}};
9624 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9625 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9626
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009627 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009628
chaviw9eaa22c2020-07-01 16:21:27 -07009629 // Release Window 2
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009630 touchAndAssertPositions(mWindow1, POINTER_1_UP, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009631 expectedPoints.pop_back();
9632
9633 // Touch Window 2
9634 mWindow2->setWindowTransform(0, -1, 1, 0);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009635 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
chaviw9eaa22c2020-07-01 16:21:27 -07009636 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009637 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
chaviw9eaa22c2020-07-01 16:21:27 -07009638
9639 // Move both windows
9640 touchedPoints = {{20, 20}, {175, 175}};
9641 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9642 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9643
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009644 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009645}
9646
9647TEST_F(InputDispatcherMultiWindowSameTokenTests, MultipleWindowsFirstTouchWithScale) {
9648 mWindow1->setWindowScale(0.5f, 0.5f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009649 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009650
9651 // Touch Window 1
9652 std::vector<PointF> touchedPoints = {PointF{10, 10}};
9653 std::vector<PointF> expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0])};
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009654 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009655
9656 // Touch Window 2
chaviw9eaa22c2020-07-01 16:21:27 -07009657 touchedPoints.push_back(PointF{150, 150});
9658 expectedPoints.push_back(getPointInWindow(mWindow2->getInfo(), touchedPoints[1]));
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009659
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009660 touchAndAssertPositions(mWindow1, POINTER_1_DOWN, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009661
9662 // Move both windows
9663 touchedPoints = {{20, 20}, {175, 175}};
9664 expectedPoints = {getPointInWindow(mWindow1->getInfo(), touchedPoints[0]),
9665 getPointInWindow(mWindow2->getInfo(), touchedPoints[1])};
9666
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009667 touchAndAssertPositions(mWindow1, AMOTION_EVENT_ACTION_MOVE, touchedPoints, expectedPoints);
Chavi Weingarten65f98b82020-01-16 18:56:50 +00009668}
9669
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009670/**
9671 * When one of the windows is slippery, the touch should not slip into the other window with the
9672 * same input channel.
9673 */
9674TEST_F(InputDispatcherMultiWindowSameTokenTests, TouchDoesNotSlipEvenIfSlippery) {
9675 mWindow1->setSlippery(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009676 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009677
9678 // Touch down in window 1
9679 mDispatcher->notifyMotion(generateMotionArgs(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009680 ui::LogicalDisplayId::DEFAULT, {{50, 50}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009681 consumeMotionEvent(mWindow1, ACTION_DOWN, {{50, 50}});
9682
9683 // Move touch to be above window 2. Even though window 1 is slippery, touch should not slip.
9684 // That means the gesture should continue normally, without any ACTION_CANCEL or ACTION_DOWN
9685 // getting generated.
9686 mDispatcher->notifyMotion(generateMotionArgs(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009687 ui::LogicalDisplayId::DEFAULT, {{150, 150}}));
Siarhei Vishniakou0f6558d2023-04-21 12:05:13 -07009688
9689 consumeMotionEvent(mWindow1, ACTION_MOVE, {{150, 150}});
9690}
9691
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009692/**
9693 * When hover starts in one window and continues into the other, there should be a HOVER_EXIT and
9694 * a HOVER_ENTER generated, even if the windows have the same token. This is because the new window
9695 * that the pointer is hovering over may have a different transform.
9696 */
9697TEST_F(InputDispatcherMultiWindowSameTokenTests, HoverIntoClone) {
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009698 mDispatcher->onWindowInfosChanged({{*mWindow1->getInfo(), *mWindow2->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009699
9700 // Start hover in window 1
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009701 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_TOUCHSCREEN)
9702 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
9703 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009704 consumeMotionEvent(mWindow1, ACTION_HOVER_ENTER,
9705 {getPointInWindow(mWindow1->getInfo(), PointF{50, 50})});
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009706 // Move hover to window 2.
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -07009707 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
9708 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
9709 .build());
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009710 consumeMotionEvent(mWindow1, ACTION_HOVER_EXIT, {{50, 50}});
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +00009711 consumeMotionEvent(mWindow2, ACTION_HOVER_ENTER,
Siarhei Vishniakoud5876ba2023-05-15 17:58:34 -07009712 {getPointInWindow(mWindow2->getInfo(), PointF{150, 150})});
9713}
9714
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009715class InputDispatcherSingleWindowAnr : public InputDispatcherTest {
9716 virtual void SetUp() override {
9717 InputDispatcherTest::SetUp();
9718
Chris Yea209fde2020-07-22 13:54:51 -07009719 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009720 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -07009721 mWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "TestWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009722 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009723 mWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -07009724 mWindow->setDispatchingTimeout(100ms);
Vishnu Nair47074b82020-08-14 11:54:47 -07009725 mWindow->setFocusable(true);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009726
9727 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009728 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009729
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009730 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -07009731 setFocusedWindow(mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009732 mWindow->consumeFocusEvent(true);
9733 }
9734
9735 virtual void TearDown() override {
9736 InputDispatcherTest::TearDown();
9737 mWindow.clear();
9738 }
9739
9740protected:
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009741 static constexpr std::chrono::duration SPY_TIMEOUT = 200ms;
Chris Yea209fde2020-07-22 13:54:51 -07009742 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009743 sp<FakeWindowHandle> mWindow;
9744 static constexpr PointF WINDOW_LOCATION = {20, 20};
9745
9746 void tapOnWindow() {
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -08009747 const auto touchingPointer = PointerBuilder(/*id=*/0, ToolType::FINGER)
9748 .x(WINDOW_LOCATION.x)
9749 .y(WINDOW_LOCATION.y);
9750 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
9751 .pointer(touchingPointer)
9752 .build());
9753 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
9754 .pointer(touchingPointer)
9755 .build());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009756 }
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009757
9758 sp<FakeWindowHandle> addSpyWindow() {
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009759 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Spy",
9760 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009761 spy->setTrustedOverlay(true);
9762 spy->setFocusable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -08009763 spy->setSpy(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009764 spy->setDispatchingTimeout(SPY_TIMEOUT);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009765 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *mWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009766 return spy;
9767 }
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009768};
9769
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009770// Send a tap and respond, which should not cause an ANR.
9771TEST_F(InputDispatcherSingleWindowAnr, WhenTouchIsConsumed_NoAnr) {
9772 tapOnWindow();
9773 mWindow->consumeMotionDown();
9774 mWindow->consumeMotionUp();
9775 ASSERT_TRUE(mDispatcher->waitForIdle());
9776 mFakePolicy->assertNotifyAnrWasNotCalled();
9777}
9778
9779// Send a regular key and respond, which should not cause an ANR.
9780TEST_F(InputDispatcherSingleWindowAnr, WhenKeyIsConsumed_NoAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009781 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009782 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009783 ASSERT_TRUE(mDispatcher->waitForIdle());
9784 mFakePolicy->assertNotifyAnrWasNotCalled();
9785}
9786
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009787TEST_F(InputDispatcherSingleWindowAnr, WhenFocusedApplicationChanges_NoAnr) {
9788 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009789 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009790 mWindow->consumeFocusEvent(false);
9791
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009792 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009793 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9794 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
9795 CONSUME_TIMEOUT_EVENT_EXPECTED,
Harry Cutts33476232023-01-30 19:57:29 +00009796 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009798 // Key will not go to window because we have no focused window.
9799 // The 'no focused window' ANR timer should start instead.
9800
9801 // Now, the focused application goes away.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009802 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, nullptr);
Siarhei Vishniakoue41c4512020-09-08 19:35:58 -05009803 // The key should get dropped and there should be no ANR.
9804
9805 ASSERT_TRUE(mDispatcher->waitForIdle());
9806 mFakePolicy->assertNotifyAnrWasNotCalled();
9807}
9808
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009809// Send an event to the app and have the app not respond right away.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009810// When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
9811// So InputDispatcher will enqueue ACTION_CANCEL event as well.
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009812TEST_F(InputDispatcherSingleWindowAnr, OnPointerDown_BasicAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009813 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009814 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9815 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009816
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009817 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009818 ASSERT_TRUE(sequenceNum);
9819 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
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009822 mWindow->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -08009823 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009824 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009825 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -08009826 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009827}
9828
9829// Send a key to the app and have the app not respond right away.
9830TEST_F(InputDispatcherSingleWindowAnr, OnKeyDown_BasicAnr) {
9831 // Inject a key, and don't respond - expect that ANR is called.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009832 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDownNoRepeat(*mDispatcher));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009833 const auto [sequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009834 ASSERT_TRUE(sequenceNum);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009835 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009836 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakou4cb50ca2020-05-26 21:43:02 -07009837 ASSERT_TRUE(mDispatcher->waitForIdle());
9838}
9839
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009840// We have a focused application, but no focused window
9841TEST_F(InputDispatcherSingleWindowAnr, FocusedApplication_NoFocusedWindow) {
Vishnu Nair47074b82020-08-14 11:54:47 -07009842 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009843 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009844 mWindow->consumeFocusEvent(false);
9845
9846 // taps on the window work as normal
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009847 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009848 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9849 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009850 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
9851 mDispatcher->waitForIdle();
9852 mFakePolicy->assertNotifyAnrWasNotCalled();
9853
9854 // Once a focused event arrives, we get an ANR for this application
9855 // We specify the injection timeout to be smaller than the application timeout, to ensure that
9856 // injection times out (instead of failing).
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009857 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009858 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9859 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT, 50ms,
Linnan Li13bf76a2024-05-05 19:18:02 +08009860 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009861 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009862 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Vishnu Naire4df8752022-09-08 09:17:55 -07009863 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009864 ASSERT_TRUE(mDispatcher->waitForIdle());
9865}
9866
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009867/**
9868 * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
9869 * there will not be an ANR.
9870 */
9871TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
9872 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009873 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009874 mWindow->consumeFocusEvent(false);
9875
9876 KeyEvent event;
Siarhei Vishniakoua7333112023-10-27 13:33:29 -07009877 static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
9878 mFakePolicy->setStaleEventTimeout(STALE_EVENT_TIMEOUT);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009879 const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
9880 std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
9881
9882 // Define a valid key down event that is stale (too old).
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009883 event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
9884 ui::LogicalDisplayId::INVALID, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN,
9885 /*flags=*/0, AKEYCODE_A, KEY_A, AMETA_NONE, /*repeatCount=*/0, eventTime,
9886 eventTime);
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009887
Hu Guofe3c8f12023-09-22 17:20:15 +08009888 const int32_t policyFlags =
9889 POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_DISABLE_KEY_REPEAT;
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009890
9891 InputEventInjectionResult result =
Harry Cutts33476232023-01-30 19:57:29 +00009892 mDispatcher->injectInputEvent(&event, /*targetUid=*/{},
Siarhei Vishniakou289e9242022-02-15 14:50:16 -08009893 InputEventInjectionSync::WAIT_FOR_RESULT,
9894 INJECT_EVENT_TIMEOUT, policyFlags);
9895 ASSERT_EQ(InputEventInjectionResult::FAILED, result)
9896 << "Injection should fail because the event is stale";
9897
9898 ASSERT_TRUE(mDispatcher->waitForIdle());
9899 mFakePolicy->assertNotifyAnrWasNotCalled();
9900 mWindow->assertNoEvents();
9901}
9902
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009903// We have a focused application, but no focused window
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009904// Make sure that we don't notify policy twice about the same ANR.
9905TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009906 const std::chrono::duration appTimeout = 400ms;
9907 mApplication->setDispatchingTimeout(appTimeout);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009908 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009909
Vishnu Nair47074b82020-08-14 11:54:47 -07009910 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009911 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009912 mWindow->consumeFocusEvent(false);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009913
9914 // Once a focused event arrives, we get an ANR for this application
9915 // We specify the injection timeout to be smaller than the application timeout, to ensure that
9916 // injection times out (instead of failing).
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009917 const std::chrono::duration eventInjectionTimeout = 100ms;
9918 ASSERT_LT(eventInjectionTimeout, appTimeout);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009919 const InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009920 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
9921 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::WAIT_FOR_RESULT,
9922 eventInjectionTimeout,
Siarhei Vishniakou06405fc2023-09-22 13:40:51 -07009923 /*allowKeyRepeat=*/false);
9924 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, result)
9925 << "result=" << ftl::enum_string(result);
9926 // We already waited for 'eventInjectionTimeout`, because the countdown started when the event
9927 // was first injected. So now we have (appTimeout - eventInjectionTimeout) left to wait.
9928 std::chrono::duration remainingWaitTime = appTimeout - eventInjectionTimeout;
9929 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(remainingWaitTime, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009930
Vishnu Naire4df8752022-09-08 09:17:55 -07009931 std::this_thread::sleep_for(appTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009932 // ANR should not be raised again. It is up to policy to do that if it desires.
9933 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009934
Siarhei Vishniakou234129c2020-10-22 22:28:12 -05009935 // If we now get a focused window, the ANR should stop, but the policy handles that via
9936 // 'notifyFocusChanged' callback. This is implemented in the policy so we can't test it here.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009937 ASSERT_TRUE(mDispatcher->waitForIdle());
9938}
9939
9940// We have a focused application, but no focused window
9941TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DropsFocusedEvents) {
Vishnu Nair47074b82020-08-14 11:54:47 -07009942 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -07009943 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009944 mWindow->consumeFocusEvent(false);
9945
9946 // Once a focused event arrives, we get an ANR for this application
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009947 ASSERT_NO_FATAL_FAILURE(assertInjectedKeyTimesOut(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009948
Vishnu Naire4df8752022-09-08 09:17:55 -07009949 const std::chrono::duration timeout = mApplication->getDispatchingTimeout(DISPATCHING_TIMEOUT);
9950 mFakePolicy->assertNotifyNoFocusedWindowAnrWasCalled(timeout, mApplication);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009951
9952 // Future focused events get dropped right away
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009953 ASSERT_EQ(InputEventInjectionResult::FAILED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009954 ASSERT_TRUE(mDispatcher->waitForIdle());
9955 mWindow->assertNoEvents();
9956}
9957
9958/**
9959 * Ensure that the implementation is valid. Since we are using multiset to keep track of the
9960 * ANR timeouts, we are allowing entries with identical timestamps in the same connection.
9961 * If we process 1 of the events, but ANR on the second event with the same timestamp,
9962 * the ANR mechanism should still work.
9963 *
9964 * In this test, we are injecting DOWN and UP events with the same timestamps, and acknowledging the
9965 * DOWN event, while not responding on the second one.
9966 */
9967TEST_F(InputDispatcherSingleWindowAnr, Anr_HandlesEventsWithIdenticalTimestamps) {
9968 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009969 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009970 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009971 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9972 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009973 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009974
9975 // Now send ACTION_UP, with identical timestamp
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -07009976 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009977 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009978 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
9979 AMOTION_EVENT_INVALID_CURSOR_POSITION},
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -08009980 500ms, InputEventInjectionSync::WAIT_FOR_RESULT, currentTime);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009981
9982 // 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 -07009983 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009984 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -08009985 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -07009986}
9987
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009988// A spy window can receive an ANR
9989TEST_F(InputDispatcherSingleWindowAnr, SpyWindowAnr) {
9990 sp<FakeWindowHandle> spy = addSpyWindow();
9991
9992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -07009993 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
9994 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009995 mWindow->consumeMotionDown();
9996
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -08009997 const auto [sequenceNum, _] = spy->receiveEvent(); // ACTION_DOWN
Prabir Pradhan1376fcd2022-01-21 09:56:35 -08009998 ASSERT_TRUE(sequenceNum);
9999 const std::chrono::duration timeout = spy->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010000 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, spy);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010001
10002 spy->finishEvent(*sequenceNum);
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010003 spy->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010004 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010005 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010006 mFakePolicy->assertNotifyWindowResponsiveWasCalled(spy->getToken(), mWindow->getPid());
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010007}
10008
10009// If an app is not responding to a key event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010010// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010011TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnKey) {
10012 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010013
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010015 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
10016 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
10017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10018 injectKeyUp(*mDispatcher, ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010019
10020 // Stuck on the ACTION_UP
10021 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010022 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010023
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010024 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010025 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010026 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10027 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010028
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010029 mWindow->consumeKeyUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010030 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010031 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010032 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010033 spy->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010034}
10035
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010036// If an app is not responding to a motion event, spy windows should continue to receive
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010037// new motion events
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010038TEST_F(InputDispatcherSingleWindowAnr, SpyWindowReceivesEventsDuringAppAnrOnMotion) {
10039 sp<FakeWindowHandle> spy = addSpyWindow();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010040
10041 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010042 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10043 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010044
10045 mWindow->consumeMotionDown();
10046 // Stuck on the ACTION_UP
10047 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010048 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010049
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010050 // New tap will go to the spy window, but not to the window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010051 tapOnWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010052 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
10053 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010054
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010055 mWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT); // still the previous motion
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010056 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010057 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010058 mWindow->assertNoEvents();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010059 spy->assertNoEvents();
10060}
10061
10062TEST_F(InputDispatcherSingleWindowAnr, UnresponsiveMonitorAnr) {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010063 mDispatcher->setMonitorDispatchingTimeoutForTest(SPY_TIMEOUT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010064
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010065 FakeMonitorReceiver monitor =
10066 FakeMonitorReceiver(*mDispatcher, "M_1", ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010067
10068 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010069 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10070 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010071
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010072 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010073 const std::optional<uint32_t> consumeSeq = monitor.receiveEvent();
10074 ASSERT_TRUE(consumeSeq);
10075
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010076 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(SPY_TIMEOUT, monitor.getToken(),
10077 MONITOR_PID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010078
10079 monitor.finishEvent(*consumeSeq);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010080 monitor.consumeMotionCancel(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080010081
10082 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010083 mFakePolicy->assertNotifyWindowResponsiveWasCalled(monitor.getToken(), MONITOR_PID);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010084}
10085
10086// If a window is unresponsive, then you get anr. if the window later catches up and starts to
10087// process events, you don't get an anr. When the window later becomes unresponsive again, you
10088// get an ANR again.
10089// 1. tap -> block on ACTION_UP -> receive ANR
10090// 2. consume all pending events (= queue becomes healthy again)
10091// 3. tap again -> block on ACTION_UP again -> receive ANR second time
10092TEST_F(InputDispatcherSingleWindowAnr, SameWindow_CanReceiveAnrTwice) {
10093 tapOnWindow();
10094
10095 mWindow->consumeMotionDown();
10096 // Block on ACTION_UP
10097 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010098 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010099 mWindow->consumeMotionUp(); // Now the connection should be healthy again
10100 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010101 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010102 mWindow->assertNoEvents();
10103
10104 tapOnWindow();
10105 mWindow->consumeMotionDown();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010106 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010107 mWindow->consumeMotionUp();
10108
10109 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010110 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010111 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010112 mWindow->assertNoEvents();
10113}
10114
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010115// If a connection remains unresponsive for a while, make sure policy is only notified once about
10116// it.
10117TEST_F(InputDispatcherSingleWindowAnr, Policy_DoesNotGetDuplicateAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010118 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010119 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10120 ui::LogicalDisplayId::DEFAULT, WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010121
10122 const std::chrono::duration windowTimeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010123 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(windowTimeout, mWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010124 std::this_thread::sleep_for(windowTimeout);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010125 // 'notifyConnectionUnresponsive' should only be called once per connection
10126 mFakePolicy->assertNotifyAnrWasNotCalled();
10127 // When the ANR happened, dispatcher should abort the current event stream via ACTION_CANCEL
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010128 mWindow->consumeMotionDown();
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080010129 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010130 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010131 mWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010132 mDispatcher->waitForIdle();
Prabir Pradhanedd96402022-02-15 01:46:16 -080010133 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010134 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010135}
10136
10137/**
10138 * 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 -070010139 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010140 */
10141TEST_F(InputDispatcherSingleWindowAnr, Key_StaysPendingWhileMotionIsProcessed) {
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010142 // The timeouts in this test are established by relying on the fact that the "key waiting for
10143 // events timeout" is equal to 500ms.
10144 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010145 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010146 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010147
10148 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010149 const auto& [downSequenceNum, downEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010150 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010151 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010152 ASSERT_TRUE(upSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010153
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010154 // Don't finish the events yet, and send a key
10155 mDispatcher->notifyKey(
10156 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10157 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10158 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010159 // Key will not be sent to the window, yet, because the window is still processing events
10160 // and the key remains pending, waiting for the touch events to be processed
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010161 // Make sure that `assertNoEvents` doesn't wait too long, because it could cause an ANR.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010162 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010163
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010164 std::this_thread::sleep_for(400ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010165 // if we wait long enough though, dispatcher will give up, and still send the key
10166 // to the focused window, even though we have not yet finished the motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010167 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010168 mWindow->finishEvent(*downSequenceNum);
10169 mWindow->finishEvent(*upSequenceNum);
10170}
10171
10172/**
10173 * If a window is processing a motion event, and then a key event comes in, the key event should
10174 * not go to the focused window until the motion is processed.
10175 * If then a new motion comes in, then the pending key event should be going to the currently
10176 * focused window right away.
10177 */
10178TEST_F(InputDispatcherSingleWindowAnr,
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010179 PendingKey_IsDeliveredWhileMotionIsProcessingAndNewTouchComesIn) {
10180 // The timeouts in this test are established by relying on the fact that the "key waiting for
10181 // events timeout" is equal to 500ms.
10182 ASSERT_EQ(mFakePolicy->getKeyWaitingForEventsTimeout(), 500ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010183 mWindow->setDispatchingTimeout(2s); // Set a long ANR timeout to prevent it from triggering
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010184 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010185
10186 tapOnWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010187 const auto& [downSequenceNum, _] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010188 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010189 const auto& [upSequenceNum, upEvent] = mWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010190 ASSERT_TRUE(upSequenceNum);
10191 // Don't finish the events yet, and send a key
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010192 mDispatcher->notifyKey(
10193 KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD)
10194 .policyFlags(DEFAULT_POLICY_FLAGS | POLICY_FLAG_DISABLE_KEY_REPEAT)
10195 .build());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010196 // At this point, key is still pending, and should not be sent to the application yet.
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010197 mWindow->assertNoEvents(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010198
10199 // Now tap down again. It should cause the pending key to go to the focused window right away.
10200 tapOnWindow();
Siarhei Vishniakouef2b4502023-12-28 11:51:47 -080010201 // Now that we tapped, we should receive the key immediately.
10202 // Since there's still room for slowness, we use 200ms, which is much less than
10203 // the "key waiting for events' timeout of 500ms minus the already waited 100ms duration.
10204 std::unique_ptr<InputEvent> keyEvent = mWindow->consume(200ms);
10205 ASSERT_NE(nullptr, keyEvent);
10206 ASSERT_EQ(InputEventType::KEY, keyEvent->getType());
10207 ASSERT_THAT(static_cast<KeyEvent&>(*keyEvent), WithKeyAction(AKEY_EVENT_ACTION_DOWN));
10208 // it doesn't matter that we haven't ack'd the other events yet. We can finish events in any
10209 // order.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010210 mWindow->finishEvent(*downSequenceNum); // first tap's ACTION_DOWN
10211 mWindow->finishEvent(*upSequenceNum); // first tap's ACTION_UP
Siarhei Vishniakou67bf2162023-11-16 13:29:50 -080010212 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10213 mWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010214 mWindow->assertNoEvents();
10215}
10216
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010217/**
10218 * Send an event to the app and have the app not respond right away.
10219 * When ANR is raised, policy will tell the dispatcher to cancel the events for that window.
10220 * So InputDispatcher will enqueue ACTION_CANCEL event as well.
10221 * At some point, the window becomes responsive again.
10222 * Ensure that subsequent events get dropped, and the next gesture is delivered.
10223 */
10224TEST_F(InputDispatcherSingleWindowAnr, TwoGesturesWithAnr) {
10225 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10226 .pointer(PointerBuilder(0, ToolType::FINGER).x(10).y(10))
10227 .build());
10228
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010229 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakouadb9fc92023-05-26 10:46:09 -070010230 ASSERT_TRUE(sequenceNum);
10231 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10232 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10233
10234 mWindow->finishEvent(*sequenceNum);
10235 mWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
10236 ASSERT_TRUE(mDispatcher->waitForIdle());
10237 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), mWindow->getPid());
10238
10239 // Now that the window is responsive, let's continue the gesture.
10240 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
10241 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10242 .build());
10243
10244 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10245 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10246 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10247 .build());
10248
10249 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
10250 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10251 .pointer(PointerBuilder(1, ToolType::FINGER).x(3).y(3))
10252 .build());
10253 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10254 .pointer(PointerBuilder(0, ToolType::FINGER).x(11).y(11))
10255 .build());
10256 // We already canceled this pointer, so the window shouldn't get any new events.
10257 mWindow->assertNoEvents();
10258
10259 // Start another one.
10260 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10261 .pointer(PointerBuilder(0, ToolType::FINGER).x(15).y(15))
10262 .build());
10263 mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10264}
10265
Prabir Pradhanfc364722024-02-08 17:51:20 +000010266// Send an event to the app and have the app not respond right away. Then remove the app window.
10267// When the window is removed, the dispatcher will cancel the events for that window.
10268// So InputDispatcher will enqueue ACTION_CANCEL event as well.
10269TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
10270 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010271 AINPUT_SOURCE_TOUCHSCREEN,
10272 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010273
10274 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10275 ASSERT_TRUE(sequenceNum);
10276
10277 // Remove the window, but the input channel should remain alive.
10278 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10279
10280 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10281 // Since the window was removed, Dispatcher does not know the PID associated with the window
10282 // anymore, so the policy is notified without the PID.
10283 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
10284 /*pid=*/std::nullopt);
10285
10286 mWindow->finishEvent(*sequenceNum);
10287 // The cancellation was generated when the window was removed, along with the focus event.
10288 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010289 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010290 mWindow->consumeFocusEvent(false);
10291 ASSERT_TRUE(mDispatcher->waitForIdle());
10292 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10293}
10294
10295// Send an event to the app and have the app not respond right away. Wait for the policy to be
10296// notified of the unresponsive window, then remove the app window.
10297TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
10298 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010299 AINPUT_SOURCE_TOUCHSCREEN,
10300 ui::LogicalDisplayId::DEFAULT, {WINDOW_LOCATION}));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010301
10302 const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
10303 ASSERT_TRUE(sequenceNum);
10304 const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
10305 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
10306
10307 // Remove the window, but the input channel should remain alive.
10308 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
10309
10310 mWindow->finishEvent(*sequenceNum);
10311 // The cancellation was generated during the ANR, and the window lost focus when it was removed.
10312 mWindow->consumeMotionEvent(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010313 AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
Prabir Pradhanfc364722024-02-08 17:51:20 +000010314 mWindow->consumeFocusEvent(false);
10315 ASSERT_TRUE(mDispatcher->waitForIdle());
10316 // Since the window was removed, Dispatcher does not know the PID associated with the window
10317 // becoming responsive, so the policy is notified without the PID.
10318 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
10319}
10320
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010321class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
10322 virtual void SetUp() override {
10323 InputDispatcherTest::SetUp();
10324
Chris Yea209fde2020-07-22 13:54:51 -070010325 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010326 mApplication->setDispatchingTimeout(100ms);
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010327 mUnfocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Unfocused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010328 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010329 mUnfocusedWindow->setFrame(Rect(0, 0, 30, 30));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010330 // Adding FLAG_WATCH_OUTSIDE_TOUCH to receive ACTION_OUTSIDE when another window is tapped
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080010331 mUnfocusedWindow->setWatchOutsideTouch(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010332
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010333 mFocusedWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Focused",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010334 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010335 mFocusedWindow->setDispatchingTimeout(100ms);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010336 mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010337
10338 // Set focused application.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010339 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Vishnu Nair47074b82020-08-14 11:54:47 -070010340 mFocusedWindow->setFocusable(true);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010341
10342 // Expect one focus window exist in display.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010343 mDispatcher->onWindowInfosChanged(
10344 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010345 setFocusedWindow(mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010346 mFocusedWindow->consumeFocusEvent(true);
10347 }
10348
10349 virtual void TearDown() override {
10350 InputDispatcherTest::TearDown();
10351
10352 mUnfocusedWindow.clear();
10353 mFocusedWindow.clear();
10354 }
10355
10356protected:
Chris Yea209fde2020-07-22 13:54:51 -070010357 std::shared_ptr<FakeApplicationHandle> mApplication;
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010358 sp<FakeWindowHandle> mUnfocusedWindow;
10359 sp<FakeWindowHandle> mFocusedWindow;
10360 static constexpr PointF UNFOCUSED_WINDOW_LOCATION = {20, 20};
10361 static constexpr PointF FOCUSED_WINDOW_LOCATION = {75, 75};
10362 static constexpr PointF LOCATION_OUTSIDE_ALL_WINDOWS = {40, 40};
10363
10364 void tapOnFocusedWindow() { tap(FOCUSED_WINDOW_LOCATION); }
10365
10366 void tapOnUnfocusedWindow() { tap(UNFOCUSED_WINDOW_LOCATION); }
10367
10368private:
10369 void tap(const PointF& location) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010370 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010371 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10372 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010373 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010374 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10375 ui::LogicalDisplayId::DEFAULT, location));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010376 }
10377};
10378
10379// If we have 2 windows that are both unresponsive, the one with the shortest timeout
10380// should be ANR'd first.
10381TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsive) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010382 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010383 injectMotionEvent(*mDispatcher,
10384 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10385 AINPUT_SOURCE_TOUCHSCREEN)
10386 .pointer(PointerBuilder(0, ToolType::FINGER)
10387 .x(FOCUSED_WINDOW_LOCATION.x)
10388 .y(FOCUSED_WINDOW_LOCATION.y))
10389 .build()));
10390 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
10391 injectMotionEvent(*mDispatcher,
10392 MotionEventBuilder(AMOTION_EVENT_ACTION_UP,
10393 AINPUT_SOURCE_TOUCHSCREEN)
10394 .pointer(PointerBuilder(0, ToolType::FINGER)
10395 .x(FOCUSED_WINDOW_LOCATION.x)
10396 .y(FOCUSED_WINDOW_LOCATION.y))
10397 .build()));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010398 mFocusedWindow->consumeMotionDown();
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010399 mFocusedWindow->consumeMotionUp();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010400 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010401 // We consumed all events, so no ANR
10402 ASSERT_TRUE(mDispatcher->waitForIdle());
10403 mFakePolicy->assertNotifyAnrWasNotCalled();
10404
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010405 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010406 injectMotionEvent(*mDispatcher,
10407 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
10408 AINPUT_SOURCE_TOUCHSCREEN)
10409 .pointer(PointerBuilder(0, ToolType::FINGER)
10410 .x(FOCUSED_WINDOW_LOCATION.x)
10411 .y(FOCUSED_WINDOW_LOCATION.y))
10412 .build()));
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010413 const auto [unfocusedSequenceNum, _] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010414 ASSERT_TRUE(unfocusedSequenceNum);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010415
10416 const std::chrono::duration timeout =
10417 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010418 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070010419
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010420 mUnfocusedWindow->finishEvent(*unfocusedSequenceNum);
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010421 mFocusedWindow->consumeMotionDown();
10422 // This cancel is generated because the connection was unresponsive
10423 mFocusedWindow->consumeMotionCancel();
10424 mFocusedWindow->assertNoEvents();
10425 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010426 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010427 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10428 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010429 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010430}
10431
10432// If we have 2 windows with identical timeouts that are both unresponsive,
10433// it doesn't matter which order they should have ANR.
10434// But we should receive ANR for both.
10435TEST_F(InputDispatcherMultiWindowAnr, TwoWindows_BothUnresponsiveWithSameTimeout) {
10436 // Set the timeout for unfocused window to match the focused window
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010437 mUnfocusedWindow->setDispatchingTimeout(
10438 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010439 mDispatcher->onWindowInfosChanged(
10440 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010441
10442 tapOnFocusedWindow();
10443 // we should have ACTION_DOWN/ACTION_UP on focused window and ACTION_OUTSIDE on unfocused window
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010444 // We don't know which window will ANR first. But both of them should happen eventually.
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010445 std::array<sp<IBinder>, 2> anrConnectionTokens = {mFakePolicy->getUnresponsiveWindowToken(
10446 mFocusedWindow->getDispatchingTimeout(
10447 DISPATCHING_TIMEOUT)),
10448 mFakePolicy->getUnresponsiveWindowToken(0ms)};
10449
10450 ASSERT_THAT(anrConnectionTokens,
10451 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10452 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010453
10454 ASSERT_TRUE(mDispatcher->waitForIdle());
10455 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010456
10457 mFocusedWindow->consumeMotionDown();
10458 mFocusedWindow->consumeMotionUp();
10459 mUnfocusedWindow->consumeMotionOutside();
10460
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010461 std::array<sp<IBinder>, 2> responsiveTokens = {mFakePolicy->getResponsiveWindowToken(),
10462 mFakePolicy->getResponsiveWindowToken()};
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010463
10464 // Both applications should be marked as responsive, in any order
Siarhei Vishniakouf83c6932023-07-07 17:48:10 -070010465 ASSERT_THAT(responsiveTokens,
10466 ::testing::UnorderedElementsAre(testing::Eq(mFocusedWindow->getToken()),
10467 testing::Eq(mUnfocusedWindow->getToken())));
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010468 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010469}
10470
10471// If a window is already not responding, the second tap on the same window should be ignored.
10472// We should also log an error to account for the dropped event (not tested here).
10473// At the same time, FLAG_WATCH_OUTSIDE_TOUCH targets should not receive any events.
10474TEST_F(InputDispatcherMultiWindowAnr, DuringAnr_SecondTapIsIgnored) {
10475 tapOnFocusedWindow();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010476 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010477 // Receive the events, but don't respond
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010478 const auto [downEventSequenceNum, downEvent] = mFocusedWindow->receiveEvent(); // ACTION_DOWN
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010479 ASSERT_TRUE(downEventSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010480 const auto [upEventSequenceNum, upEvent] = mFocusedWindow->receiveEvent(); // ACTION_UP
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010481 ASSERT_TRUE(upEventSequenceNum);
10482 const std::chrono::duration timeout =
10483 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010484 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010485
10486 // Tap once again
10487 // We cannot use "tapOnFocusedWindow" because it asserts the injection result to be success
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010488 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010489 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10490 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010491 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010492 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010493 FOCUSED_WINDOW_LOCATION));
10494 // Unfocused window does not receive ACTION_OUTSIDE because the tapped window is not a
10495 // valid touch target
10496 mUnfocusedWindow->assertNoEvents();
10497
10498 // Consume the first tap
10499 mFocusedWindow->finishEvent(*downEventSequenceNum);
10500 mFocusedWindow->finishEvent(*upEventSequenceNum);
10501 ASSERT_TRUE(mDispatcher->waitForIdle());
10502 // The second tap did not go to the focused window
10503 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010504 // Since all events are finished, connection should be deemed healthy again
Prabir Pradhanedd96402022-02-15 01:46:16 -080010505 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10506 mFocusedWindow->getPid());
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010507 mFakePolicy->assertNotifyAnrWasNotCalled();
10508}
10509
10510// If you tap outside of all windows, there will not be ANR
10511TEST_F(InputDispatcherMultiWindowAnr, TapOutsideAllWindows_DoesNotAnr) {
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010512 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010513 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10514 ui::LogicalDisplayId::DEFAULT, LOCATION_OUTSIDE_ALL_WINDOWS));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010515 ASSERT_TRUE(mDispatcher->waitForIdle());
10516 mFakePolicy->assertNotifyAnrWasNotCalled();
10517}
10518
10519// Since the focused window is paused, tapping on it should not produce any events
10520TEST_F(InputDispatcherMultiWindowAnr, Window_CanBePaused) {
10521 mFocusedWindow->setPaused(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010522 mDispatcher->onWindowInfosChanged(
10523 {{*mUnfocusedWindow->getInfo(), *mFocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010524
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010525 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010526 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
10527 ui::LogicalDisplayId::DEFAULT, FOCUSED_WINDOW_LOCATION));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010528
10529 std::this_thread::sleep_for(mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT));
10530 ASSERT_TRUE(mDispatcher->waitForIdle());
10531 // Should not ANR because the window is paused, and touches shouldn't go to it
10532 mFakePolicy->assertNotifyAnrWasNotCalled();
10533
10534 mFocusedWindow->assertNoEvents();
10535 mUnfocusedWindow->assertNoEvents();
10536}
10537
10538/**
10539 * 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 -070010540 * not get delivered to the focused window until the motion is processed.
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010541 * If a different window becomes focused at this time, the key should go to that window instead.
10542 *
10543 * Warning!!!
10544 * This test depends on the value of android::inputdispatcher::KEY_WAITING_FOR_MOTION_TIMEOUT
10545 * and the injection timeout that we specify when injecting the key.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010546 * We must have the injection timeout (100ms) be smaller than
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010547 * KEY_WAITING_FOR_MOTION_TIMEOUT (currently 500ms).
10548 *
10549 * If that value changes, this test should also change.
10550 */
10551TEST_F(InputDispatcherMultiWindowAnr, PendingKey_GoesToNewlyFocusedWindow) {
10552 // Set a long ANR timeout to prevent it from triggering
10553 mFocusedWindow->setDispatchingTimeout(2s);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010554 mDispatcher->onWindowInfosChanged(
10555 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010556
10557 tapOnUnfocusedWindow();
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010558 const auto [downSequenceNum, downEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010559 ASSERT_TRUE(downSequenceNum);
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010560 const auto [upSequenceNum, upEvent] = mUnfocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010561 ASSERT_TRUE(upSequenceNum);
10562 // Don't finish the events yet, and send a key
10563 // Injection will succeed because we will eventually give up and send the key to the focused
10564 // window even if motions are still being processed.
10565
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010566 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010567 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10568 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010569 /*injectionTimeout=*/100ms);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010570 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010571 // Key will not be sent to the window, yet, because the window is still processing events
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010572 // and the key remains pending, waiting for the touch events to be processed.
10573 // Make sure `assertNoEvents` doesn't take too long. It uses CONSUME_TIMEOUT_NO_EVENT_EXPECTED
10574 // under the hood.
10575 static_assert(CONSUME_TIMEOUT_NO_EVENT_EXPECTED < 100ms);
10576 mFocusedWindow->assertNoEvents();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010577
10578 // Switch the focus to the "unfocused" window that we tapped. Expect the key to go there
Vishnu Nair47074b82020-08-14 11:54:47 -070010579 mFocusedWindow->setFocusable(false);
10580 mUnfocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010581 mDispatcher->onWindowInfosChanged(
10582 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010583 setFocusedWindow(mUnfocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010584
10585 // Focus events should precede the key events
10586 mUnfocusedWindow->consumeFocusEvent(true);
10587 mFocusedWindow->consumeFocusEvent(false);
10588
10589 // Finish the tap events, which should unblock dispatcher
10590 mUnfocusedWindow->finishEvent(*downSequenceNum);
10591 mUnfocusedWindow->finishEvent(*upSequenceNum);
10592
10593 // Now that all queues are cleared and no backlog in the connections, the key event
10594 // can finally go to the newly focused "mUnfocusedWindow".
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010595 mUnfocusedWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010596 mFocusedWindow->assertNoEvents();
10597 mUnfocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010598 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010599}
10600
10601// When the touch stream is split across 2 windows, and one of them does not respond,
10602// then ANR should be raised and the touch should be canceled for the unresponsive window.
10603// The other window should not be affected by that.
10604TEST_F(InputDispatcherMultiWindowAnr, SplitTouch_SingleWindowAnr) {
10605 // Touch Window 1
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010606 mDispatcher->notifyMotion(
10607 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10608 ui::LogicalDisplayId::DEFAULT, {FOCUSED_WINDOW_LOCATION}));
10609 mUnfocusedWindow->consumeMotionOutside(ui::LogicalDisplayId::DEFAULT, /*flags=*/0);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010610
10611 // Touch Window 2
Prabir Pradhan678438e2023-04-13 19:32:51 +000010612 mDispatcher->notifyMotion(
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010613 generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10614 ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan678438e2023-04-13 19:32:51 +000010615 {FOCUSED_WINDOW_LOCATION, UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010616
10617 const std::chrono::duration timeout =
10618 mFocusedWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
Prabir Pradhanedd96402022-02-15 01:46:16 -080010619 mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mFocusedWindow);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010620
10621 mUnfocusedWindow->consumeMotionDown();
10622 mFocusedWindow->consumeMotionDown();
10623 // Focused window may or may not receive ACTION_MOVE
10624 // But it should definitely receive ACTION_CANCEL due to the ANR
Siarhei Vishniakoud3061ab2023-12-18 20:41:08 -080010625 const auto [moveOrCancelSequenceNum, event] = mFocusedWindow->receiveEvent();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010626 ASSERT_TRUE(moveOrCancelSequenceNum);
10627 mFocusedWindow->finishEvent(*moveOrCancelSequenceNum);
10628 ASSERT_NE(nullptr, event);
Siarhei Vishniakou63b63612023-04-12 11:00:23 -070010629 ASSERT_EQ(event->getType(), InputEventType::MOTION);
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010630 MotionEvent& motionEvent = static_cast<MotionEvent&>(*event);
10631 if (motionEvent.getAction() == AMOTION_EVENT_ACTION_MOVE) {
10632 mFocusedWindow->consumeMotionCancel();
10633 } else {
10634 ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionEvent.getAction());
10635 }
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010636 ASSERT_TRUE(mDispatcher->waitForIdle());
Prabir Pradhanedd96402022-02-15 01:46:16 -080010637 mFakePolicy->assertNotifyWindowResponsiveWasCalled(mFocusedWindow->getToken(),
10638 mFocusedWindow->getPid());
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010639
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010640 mUnfocusedWindow->assertNoEvents();
10641 mFocusedWindow->assertNoEvents();
Siarhei Vishniakou234129c2020-10-22 22:28:12 -050010642 mFakePolicy->assertNotifyAnrWasNotCalled();
Siarhei Vishniakoud44dddf2020-03-25 16:16:40 -070010643}
10644
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010645/**
10646 * If we have no focused window, and a key comes in, we start the ANR timer.
10647 * The focused application should add a focused window before the timer runs out to prevent ANR.
10648 *
10649 * If the user touches another application during this time, the key should be dropped.
10650 * Next, if a new focused window comes in, without toggling the focused application,
10651 * then no ANR should occur.
10652 *
10653 * Normally, we would expect the new focused window to be accompanied by 'setFocusedApplication',
10654 * but in some cases the policy may not update the focused application.
10655 */
10656TEST_F(InputDispatcherMultiWindowAnr, FocusedWindowWithoutSetFocusedApplication_NoAnr) {
10657 std::shared_ptr<FakeApplicationHandle> focusedApplication =
10658 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakouc033dfb2023-10-03 10:45:16 -070010659 focusedApplication->setDispatchingTimeout(300ms);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010660 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, focusedApplication);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010661 // The application that owns 'mFocusedWindow' and 'mUnfocusedWindow' is not focused.
10662 mFocusedWindow->setFocusable(false);
10663
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010664 mDispatcher->onWindowInfosChanged(
10665 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010666 mFocusedWindow->consumeFocusEvent(false);
10667
10668 // Send a key. The ANR timer should start because there is no focused window.
10669 // 'focusedApplication' will get blamed if this timer completes.
10670 // Key will not be sent anywhere because we have no focused window. It will remain pending.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010671 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010672 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10673 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010674 /*injectionTimeout=*/100ms,
Harry Cutts33476232023-01-30 19:57:29 +000010675 /*allowKeyRepeat=*/false);
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010676 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010677
10678 // Wait until dispatcher starts the "no focused window" timer. If we don't wait here,
10679 // then the injected touches won't cause the focused event to get dropped.
10680 // The dispatcher only checks for whether the queue should be pruned upon queueing.
10681 // If we inject the touch right away and the ANR timer hasn't started, the touch event would
10682 // simply be added to the queue without 'shouldPruneInboundQueueLocked' returning 'true'.
10683 // For this test, it means that the key would get delivered to the window once it becomes
10684 // focused.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010685 std::this_thread::sleep_for(100ms);
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010686
10687 // Touch unfocused window. This should force the pending key to get dropped.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010688 mDispatcher->notifyMotion(
10689 generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
10690 ui::LogicalDisplayId::DEFAULT, {UNFOCUSED_WINDOW_LOCATION}));
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010691
10692 // We do not consume the motion right away, because that would require dispatcher to first
10693 // process (== drop) the key event, and by that time, ANR will be raised.
10694 // Set the focused window first.
10695 mFocusedWindow->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010696 mDispatcher->onWindowInfosChanged(
10697 {{*mFocusedWindow->getInfo(), *mUnfocusedWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakouf56b2692020-09-08 19:43:33 -050010698 setFocusedWindow(mFocusedWindow);
10699 mFocusedWindow->consumeFocusEvent(true);
10700 // We do not call "setFocusedApplication" here, even though the newly focused window belongs
10701 // to another application. This could be a bug / behaviour in the policy.
10702
10703 mUnfocusedWindow->consumeMotionDown();
10704
10705 ASSERT_TRUE(mDispatcher->waitForIdle());
10706 // Should not ANR because we actually have a focused window. It was just added too slowly.
10707 ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertNotifyAnrWasNotCalled());
10708}
10709
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010710/**
10711 * If we are pruning input queue, we should never drop pointer events. Otherwise, we risk having
10712 * an inconsistent event stream inside the dispatcher. In this test, we make sure that the
10713 * dispatcher doesn't prune pointer events incorrectly.
10714 *
10715 * This test reproduces a crash in InputDispatcher.
10716 * To reproduce the crash, we need to simulate the conditions for "pruning input queue" to occur.
10717 *
10718 * Keep the currently focused application (mApplication), and have no focused window.
10719 * We set up two additional windows:
10720 * 1) The navigation bar window. This simulates the system "NavigationBar", which is used in the
10721 * 3-button navigation mode. This window injects a BACK button when it's touched. 2) The application
10722 * window. This window is not focusable, but is touchable.
10723 *
10724 * We first touch the navigation bar, which causes it to inject a key. Since there's no focused
10725 * window, the dispatcher doesn't process this key, and all other events inside dispatcher are now
10726 * blocked. The dispatcher is waiting for 'mApplication' to add a focused window.
10727 *
10728 * Now, we touch "Another window". This window is owned by a different application than
10729 * 'mApplication'. This causes the dispatcher to stop waiting for 'mApplication' to add a focused
10730 * window. Now, the "pruning input queue" behaviour should kick in, and the dispatcher should start
10731 * dropping the events from its queue. Ensure that no crash occurs.
10732 *
10733 * In this test, we are setting long timeouts to prevent ANRs and events dropped due to being stale.
10734 * This does not affect the test running time.
10735 */
10736TEST_F(InputDispatcherMultiWindowAnr, PruningInputQueueShouldNotDropPointerEvents) {
10737 std::shared_ptr<FakeApplicationHandle> systemUiApplication =
10738 std::make_shared<FakeApplicationHandle>();
10739 systemUiApplication->setDispatchingTimeout(3000ms);
10740 mFakePolicy->setStaleEventTimeout(3000ms);
10741 sp<FakeWindowHandle> navigationBar =
10742 sp<FakeWindowHandle>::make(systemUiApplication, mDispatcher, "NavigationBar",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010743 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010744 navigationBar->setFocusable(false);
10745 navigationBar->setWatchOutsideTouch(true);
10746 navigationBar->setFrame(Rect(0, 0, 100, 100));
10747
10748 mApplication->setDispatchingTimeout(3000ms);
10749 // 'mApplication' is already focused, but we call it again here to make it explicit.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010750 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApplication);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010751
10752 std::shared_ptr<FakeApplicationHandle> anotherApplication =
10753 std::make_shared<FakeApplicationHandle>();
10754 sp<FakeWindowHandle> appWindow =
10755 sp<FakeWindowHandle>::make(anotherApplication, mDispatcher, "Another window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010756 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010757 appWindow->setFocusable(false);
10758 appWindow->setFrame(Rect(100, 100, 200, 200));
10759
10760 mDispatcher->onWindowInfosChanged(
10761 {{*navigationBar->getInfo(), *appWindow->getInfo()}, {}, 0, 0});
10762 // 'mFocusedWindow' is no longer in the dispatcher window list, and therefore loses focus
10763 mFocusedWindow->consumeFocusEvent(false);
10764
10765 // Touch down the navigation bar. It consumes the touch and injects a key into the dispatcher
10766 // in response.
10767 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10768 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10769 .build());
10770 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10771
10772 // Key will not be sent anywhere because we have no focused window. It will remain pending.
10773 // Pretend we are injecting KEYCODE_BACK, but it doesn't actually matter what key it is.
10774 InputEventInjectionResult result =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010775 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
10776 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010777 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010778 /*allowKeyRepeat=*/false);
10779 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10780
10781 // Finish the gesture - lift up finger and inject ACTION_UP key event
10782 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
10783 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
10784 .build());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010785 result = injectKey(*mDispatcher, AKEY_EVENT_ACTION_UP, /*repeatCount=*/0,
10786 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE,
Linnan Li13bf76a2024-05-05 19:18:02 +080010787 /*injectionTimeout=*/100ms,
Siarhei Vishniakou99e407b2023-12-26 18:09:32 -080010788 /*allowKeyRepeat=*/false);
10789 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, result);
10790 // The key that was injected is blocking the dispatcher, so the navigation bar shouldn't be
10791 // getting any events yet.
10792 navigationBar->assertNoEvents();
10793
10794 // Now touch "Another window". This touch is going to a different application than the one we
10795 // are waiting for (which is 'mApplication').
10796 // This should cause the dispatcher to drop the pending focus-dispatched events (like the key
10797 // trying to be injected) and to continue processing the rest of the events in the original
10798 // order.
10799 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
10800 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(150))
10801 .build());
10802 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_UP));
10803 navigationBar->consumeMotionEvent(WithMotionAction(ACTION_OUTSIDE));
10804 appWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
10805
10806 appWindow->assertNoEvents();
10807 navigationBar->assertNoEvents();
10808}
10809
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010810// These tests ensure we cannot send touch events to a window that's positioned behind a window
10811// that has feature NO_INPUT_CHANNEL.
10812// Layout:
10813// Top (closest to user)
10814// mNoInputWindow (above all windows)
10815// mBottomWindow
10816// Bottom (furthest from user)
10817class InputDispatcherMultiWindowOcclusionTests : public InputDispatcherTest {
10818 virtual void SetUp() override {
10819 InputDispatcherTest::SetUp();
10820
10821 mApplication = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010822 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
10823 "Window without input channel",
10824 ui::LogicalDisplayId::DEFAULT,
10825 /*createInputChannel=*/false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010826 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010827 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
10828 // It's perfectly valid for this window to not have an associated input channel
10829
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010830 mBottomWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher, "Bottom window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010831 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010832 mBottomWindow->setFrame(Rect(0, 0, 100, 100));
10833
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010834 mDispatcher->onWindowInfosChanged(
10835 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010836 }
10837
10838protected:
10839 std::shared_ptr<FakeApplicationHandle> mApplication;
10840 sp<FakeWindowHandle> mNoInputWindow;
10841 sp<FakeWindowHandle> mBottomWindow;
10842};
10843
10844TEST_F(InputDispatcherMultiWindowOcclusionTests, NoInputChannelFeature_DropsTouches) {
10845 PointF touchedPoint = {10, 10};
10846
Prabir Pradhan678438e2023-04-13 19:32:51 +000010847 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010848 AINPUT_SOURCE_TOUCHSCREEN,
10849 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010850
10851 mNoInputWindow->assertNoEvents();
10852 // Even though the window 'mNoInputWindow' positioned above 'mBottomWindow' does not have
10853 // an input channel, it is not marked as FLAG_NOT_TOUCHABLE,
10854 // and therefore should prevent mBottomWindow from receiving touches
10855 mBottomWindow->assertNoEvents();
10856}
10857
10858/**
10859 * If a window has feature NO_INPUT_CHANNEL, and somehow (by mistake) still has an input channel,
10860 * ensure that this window does not receive any touches, and blocks touches to windows underneath.
10861 */
10862TEST_F(InputDispatcherMultiWindowOcclusionTests,
10863 NoInputChannelFeature_DropsTouchesWithValidChannel) {
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070010864 mNoInputWindow = sp<FakeWindowHandle>::make(mApplication, mDispatcher,
10865 "Window with input channel and NO_INPUT_CHANNEL",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010866 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010867
Prabir Pradhan51e7db02022-02-07 06:02:57 -080010868 mNoInputWindow->setNoInputChannel(true);
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010869 mNoInputWindow->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010870 mDispatcher->onWindowInfosChanged(
10871 {{*mNoInputWindow->getInfo(), *mBottomWindow->getInfo()}, {}, 0, 0});
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010872
10873 PointF touchedPoint = {10, 10};
10874
Prabir Pradhan678438e2023-04-13 19:32:51 +000010875 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010876 AINPUT_SOURCE_TOUCHSCREEN,
10877 ui::LogicalDisplayId::DEFAULT, {touchedPoint}));
Siarhei Vishniakoua2862a02020-07-20 16:36:46 -050010878
10879 mNoInputWindow->assertNoEvents();
10880 mBottomWindow->assertNoEvents();
10881}
10882
Vishnu Nair958da932020-08-21 17:12:37 -070010883class InputDispatcherMirrorWindowFocusTests : public InputDispatcherTest {
10884protected:
10885 std::shared_ptr<FakeApplicationHandle> mApp;
10886 sp<FakeWindowHandle> mWindow;
10887 sp<FakeWindowHandle> mMirror;
10888
10889 virtual void SetUp() override {
10890 InputDispatcherTest::SetUp();
10891 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010892 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
10893 ui::LogicalDisplayId::DEFAULT);
10894 mMirror = mWindow->clone(ui::LogicalDisplayId::DEFAULT);
10895 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Vishnu Nair958da932020-08-21 17:12:37 -070010896 mWindow->setFocusable(true);
10897 mMirror->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010898 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010899 }
10900};
10901
10902TEST_F(InputDispatcherMirrorWindowFocusTests, CanGetFocus) {
10903 // Request focus on a mirrored window
10904 setFocusedWindow(mMirror);
10905
10906 // window gets focused
10907 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010908 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010909 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010910 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010911}
10912
10913// A focused & mirrored window remains focused only if the window and its mirror are both
10914// focusable.
10915TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAllWindowsFocusable) {
10916 setFocusedWindow(mMirror);
10917
Prabir Pradhanbb3f1c02024-01-04 20:17:14 +000010918 // window gets focused because it is above the mirror
Vishnu Nair958da932020-08-21 17:12:37 -070010919 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010920 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010921 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010922 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010923 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010924 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010925 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010926
10927 mMirror->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010928 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010929
10930 // window loses focus since one of the windows associated with the token in not focusable
10931 mWindow->consumeFocusEvent(false);
10932
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010933 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010934 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010935 mWindow->assertNoEvents();
10936}
10937
10938// A focused & mirrored window remains focused until the window and its mirror both become
10939// invisible.
10940TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedIfAnyWindowVisible) {
10941 setFocusedWindow(mMirror);
10942
10943 // window gets focused
10944 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010946 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010947 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010948 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010949 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010950 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010951
10952 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010953 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010954
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010955 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010956 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010957 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010958 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010959 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010960 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010961
10962 mWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010963 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010964
10965 // window loses focus only after all windows associated with the token become invisible.
10966 mWindow->consumeFocusEvent(false);
10967
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010968 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010969 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070010970 mWindow->assertNoEvents();
10971}
10972
10973// A focused & mirrored window remains focused until both windows are removed.
10974TEST_F(InputDispatcherMirrorWindowFocusTests, FocusedWhileWindowsAlive) {
10975 setFocusedWindow(mMirror);
10976
10977 // window gets focused
10978 mWindow->consumeFocusEvent(true);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010979 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010980 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010981 mWindow->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010982 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010983 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010984 mWindow->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010985
10986 // single window is removed but the window token remains focused
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010987 mDispatcher->onWindowInfosChanged({{*mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010988
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010989 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010990 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010991 mMirror->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070010992 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080010993 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070010994 mMirror->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Vishnu Nair958da932020-08-21 17:12:37 -070010995
10996 // Both windows are removed
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070010997 mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070010998 mWindow->consumeFocusEvent(false);
10999
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011000 ASSERT_EQ(InputEventInjectionResult::TIMED_OUT, injectKeyDown(*mDispatcher))
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011001 << "Inject key event should return InputEventInjectionResult::TIMED_OUT";
Vishnu Nair958da932020-08-21 17:12:37 -070011002 mWindow->assertNoEvents();
11003}
11004
11005// Focus request can be pending until one window becomes visible.
11006TEST_F(InputDispatcherMirrorWindowFocusTests, DeferFocusWhenInvisible) {
11007 // Request focus on an invisible mirror.
11008 mWindow->setVisible(false);
11009 mMirror->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011010 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011011 setFocusedWindow(mMirror);
11012
11013 // Injected key goes to pending queue.
Siarhei Vishniakouae6229e2019-12-30 16:23:19 -080011014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011015 injectKey(*mDispatcher, AKEY_EVENT_ACTION_DOWN, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011016 ui::LogicalDisplayId::DEFAULT, InputEventInjectionSync::NONE));
Vishnu Nair958da932020-08-21 17:12:37 -070011017
11018 mMirror->setVisible(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011019 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mMirror->getInfo()}, {}, 0, 0});
Vishnu Nair958da932020-08-21 17:12:37 -070011020
11021 // window gets focused
11022 mWindow->consumeFocusEvent(true);
11023 // window gets the pending key event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011024 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair958da932020-08-21 17:12:37 -070011025}
Prabir Pradhan99987712020-11-10 18:43:05 -080011026
11027class InputDispatcherPointerCaptureTests : public InputDispatcherTest {
11028protected:
11029 std::shared_ptr<FakeApplicationHandle> mApp;
11030 sp<FakeWindowHandle> mWindow;
11031 sp<FakeWindowHandle> mSecondWindow;
11032
11033 void SetUp() override {
11034 InputDispatcherTest::SetUp();
11035 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011036 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11037 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080011038 mWindow->setFocusable(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011039 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11040 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan99987712020-11-10 18:43:05 -080011041 mSecondWindow->setFocusable(true);
11042
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011043 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011044 mDispatcher->onWindowInfosChanged(
11045 {{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Prabir Pradhan99987712020-11-10 18:43:05 -080011046
11047 setFocusedWindow(mWindow);
11048 mWindow->consumeFocusEvent(true);
11049 }
11050
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011051 void notifyPointerCaptureChanged(const PointerCaptureRequest& request) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011052 mDispatcher->notifyPointerCaptureChanged(generatePointerCaptureChangedArgs(request));
Prabir Pradhan99987712020-11-10 18:43:05 -080011053 }
11054
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011055 PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
11056 bool enabled) {
Prabir Pradhan99987712020-11-10 18:43:05 -080011057 mDispatcher->requestPointerCapture(window->getToken(), enabled);
Hiroki Sato25040232024-02-22 17:21:22 +090011058 auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011059 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011060 window->consumeCaptureEvent(enabled);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011061 return request;
Prabir Pradhan99987712020-11-10 18:43:05 -080011062 }
11063};
11064
11065TEST_F(InputDispatcherPointerCaptureTests, EnablePointerCaptureWhenFocused) {
11066 // Ensure that capture cannot be obtained for unfocused windows.
11067 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11068 mFakePolicy->assertSetPointerCaptureNotCalled();
11069 mSecondWindow->assertNoEvents();
11070
11071 // Ensure that capture can be enabled from the focus window.
11072 requestAndVerifyPointerCapture(mWindow, true);
11073
11074 // Ensure that capture cannot be disabled from a window that does not have capture.
11075 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), false);
11076 mFakePolicy->assertSetPointerCaptureNotCalled();
11077
11078 // Ensure that capture can be disabled from the window with capture.
11079 requestAndVerifyPointerCapture(mWindow, false);
11080}
11081
11082TEST_F(InputDispatcherPointerCaptureTests, DisablesPointerCaptureAfterWindowLosesFocus) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011083 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011084
11085 setFocusedWindow(mSecondWindow);
11086
11087 // Ensure that the capture disabled event was sent first.
11088 mWindow->consumeCaptureEvent(false);
11089 mWindow->consumeFocusEvent(false);
11090 mSecondWindow->consumeFocusEvent(true);
Hiroki Sato25040232024-02-22 17:21:22 +090011091 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011092
11093 // Ensure that additional state changes from InputReader are not sent to the window.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011094 notifyPointerCaptureChanged({});
11095 notifyPointerCaptureChanged(request);
11096 notifyPointerCaptureChanged({});
Prabir Pradhan99987712020-11-10 18:43:05 -080011097 mWindow->assertNoEvents();
11098 mSecondWindow->assertNoEvents();
11099 mFakePolicy->assertSetPointerCaptureNotCalled();
11100}
11101
11102TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerCapture) {
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011103 auto request = requestAndVerifyPointerCapture(mWindow, true);
Prabir Pradhan99987712020-11-10 18:43:05 -080011104
11105 // InputReader unexpectedly disables and enables pointer capture.
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011106 notifyPointerCaptureChanged({});
11107 notifyPointerCaptureChanged(request);
Prabir Pradhan99987712020-11-10 18:43:05 -080011108
11109 // Ensure that Pointer Capture is disabled.
Hiroki Sato25040232024-02-22 17:21:22 +090011110 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan99987712020-11-10 18:43:05 -080011111 mWindow->consumeCaptureEvent(false);
11112 mWindow->assertNoEvents();
11113}
11114
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011115TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
11116 requestAndVerifyPointerCapture(mWindow, true);
11117
11118 // The first window loses focus.
11119 setFocusedWindow(mSecondWindow);
Hiroki Sato25040232024-02-22 17:21:22 +090011120 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011121 mWindow->consumeCaptureEvent(false);
11122
11123 // Request Pointer Capture from the second window before the notification from InputReader
11124 // arrives.
11125 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011126 auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011127
11128 // InputReader notifies Pointer Capture was disabled (because of the focus change).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011129 notifyPointerCaptureChanged({});
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011130
11131 // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011132 notifyPointerCaptureChanged(request);
Prabir Pradhan167e6d92021-02-04 16:18:17 -080011133
11134 mSecondWindow->consumeFocusEvent(true);
11135 mSecondWindow->consumeCaptureEvent(true);
11136}
11137
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011138TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
11139 // App repeatedly enables and disables capture.
11140 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011141 auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011142 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011143 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011144 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011145 auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan5cc1a692021-08-06 14:01:18 +000011146
11147 // InputReader notifies that PointerCapture has been enabled for the first request. Since the
11148 // first request is now stale, this should do nothing.
11149 notifyPointerCaptureChanged(firstRequest);
11150 mWindow->assertNoEvents();
11151
11152 // InputReader notifies that the second request was enabled.
11153 notifyPointerCaptureChanged(secondRequest);
11154 mWindow->consumeCaptureEvent(true);
11155}
11156
Prabir Pradhan7092e262022-05-03 16:51:09 +000011157TEST_F(InputDispatcherPointerCaptureTests, RapidToggleRequests) {
11158 requestAndVerifyPointerCapture(mWindow, true);
11159
11160 // App toggles pointer capture off and on.
11161 mDispatcher->requestPointerCapture(mWindow->getToken(), false);
Hiroki Sato25040232024-02-22 17:21:22 +090011162 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011163
11164 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
Hiroki Sato25040232024-02-22 17:21:22 +090011165 auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
Prabir Pradhan7092e262022-05-03 16:51:09 +000011166
11167 // InputReader notifies that the latest "enable" request was processed, while skipping over the
11168 // preceding "disable" request.
11169 notifyPointerCaptureChanged(enableRequest);
11170
11171 // Since pointer capture was never disabled during the rapid toggle, the window does not receive
11172 // any notifications.
11173 mWindow->assertNoEvents();
11174}
11175
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070011176/**
11177 * One window. Hover mouse in the window, and then start capture. Make sure that the relative
11178 * mouse movements don't affect the previous mouse hovering state.
11179 * When pointer capture is enabled, the incoming events are always ACTION_MOVE (there are no
11180 * HOVER_MOVE events).
11181 */
11182TEST_F(InputDispatcherPointerCaptureTests, MouseHoverAndPointerCapture) {
11183 // Mouse hover on the window
11184 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
11185 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11186 .build());
11187 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11188 .pointer(PointerBuilder(0, ToolType::MOUSE).x(100).y(110))
11189 .build());
11190
11191 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_ENTER)));
11192 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_MOVE)));
11193
11194 // Start pointer capture
11195 requestAndVerifyPointerCapture(mWindow, true);
11196
11197 // Send some relative mouse movements and receive them in the window.
11198 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_MOUSE_RELATIVE)
11199 .pointer(PointerBuilder(0, ToolType::MOUSE).x(10).y(11))
11200 .build());
11201 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithCoords(10, 11),
11202 WithSource(AINPUT_SOURCE_MOUSE_RELATIVE)));
11203
11204 // Stop pointer capture
11205 requestAndVerifyPointerCapture(mWindow, false);
11206
11207 // Continue hovering on the window
11208 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
11209 .pointer(PointerBuilder(0, ToolType::MOUSE).x(105).y(115))
11210 .build());
11211 mWindow->consumeMotionEvent(
11212 AllOf(WithMotionAction(ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)));
11213
11214 mWindow->assertNoEvents();
11215}
11216
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011217TEST_F(InputDispatcherPointerCaptureTests, MultiDisplayPointerCapture) {
11218 // The default display is the focused display to begin with.
11219 requestAndVerifyPointerCapture(mWindow, true);
11220
11221 // Move the second window to a second display, make it the focused window on that display.
11222 mSecondWindow->editInfo()->displayId = SECOND_DISPLAY_ID;
11223 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
11224 setFocusedWindow(mSecondWindow);
11225 mSecondWindow->consumeFocusEvent(true);
11226
11227 mWindow->assertNoEvents();
11228
11229 // The second window cannot gain capture because it is not on the focused display.
11230 mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
11231 mFakePolicy->assertSetPointerCaptureNotCalled();
11232 mSecondWindow->assertNoEvents();
11233
11234 // Make the second display the focused display.
11235 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
Arpit Singhb65e2bd2024-06-03 09:48:16 +000011236 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
Prabir Pradhan9d3d5612024-06-06 20:34:26 +000011237
11238 // This causes the first window to lose pointer capture, and it's unable to request capture.
11239 mWindow->consumeCaptureEvent(false);
11240 mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
11241
11242 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11243 mFakePolicy->assertSetPointerCaptureNotCalled();
11244
11245 // The second window is now able to gain pointer capture successfully.
11246 requestAndVerifyPointerCapture(mSecondWindow, true);
11247}
11248
Hiroki Sato25040232024-02-22 17:21:22 +090011249using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
11250
11251TEST_F(InputDispatcherPointerCaptureDeathTest,
11252 NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
11253 testing::GTEST_FLAG(death_test_style) = "threadsafe";
11254 ScopedSilentDeath _silentDeath;
11255
11256 mDispatcher->requestPointerCapture(mWindow->getToken(), true);
11257 auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
11258
11259 // Dispatch a pointer changed event with a wrong token.
11260 request.window = mSecondWindow->getToken();
11261 ASSERT_DEATH(
11262 {
11263 notifyPointerCaptureChanged(request);
11264 mSecondWindow->consumeCaptureEvent(true);
11265 },
11266 "Unexpected requested window for Pointer Capture.");
11267}
11268
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011269class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
11270protected:
11271 constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
Bernardo Rufino7393d172021-02-26 13:56:11 +000011272
11273 constexpr static const float OPACITY_ABOVE_THRESHOLD = 0.9;
11274 static_assert(OPACITY_ABOVE_THRESHOLD > MAXIMUM_OBSCURING_OPACITY);
11275
11276 constexpr static const float OPACITY_BELOW_THRESHOLD = 0.7;
11277 static_assert(OPACITY_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11278
11279 // When combined twice, ie 1 - (1 - 0.5)*(1 - 0.5) = 0.75 < 8, is still below the threshold
11280 constexpr static const float OPACITY_FAR_BELOW_THRESHOLD = 0.5;
11281 static_assert(OPACITY_FAR_BELOW_THRESHOLD < MAXIMUM_OBSCURING_OPACITY);
11282 static_assert(1 - (1 - OPACITY_FAR_BELOW_THRESHOLD) * (1 - OPACITY_FAR_BELOW_THRESHOLD) <
11283 MAXIMUM_OBSCURING_OPACITY);
11284
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011285 static constexpr gui::Uid TOUCHED_APP_UID{10001};
11286 static constexpr gui::Uid APP_B_UID{10002};
11287 static constexpr gui::Uid APP_C_UID{10003};
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011288
11289 sp<FakeWindowHandle> mTouchWindow;
11290
11291 virtual void SetUp() override {
11292 InputDispatcherTest::SetUp();
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011293 mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011294 mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
11295 }
11296
11297 virtual void TearDown() override {
11298 InputDispatcherTest::TearDown();
11299 mTouchWindow.clear();
11300 }
11301
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011302 sp<FakeWindowHandle> getOccludingWindow(gui::Uid uid, std::string name, TouchOcclusionMode mode,
chaviw3277faf2021-05-19 16:45:23 -050011303 float alpha = 1.0f) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011304 sp<FakeWindowHandle> window = getWindow(uid, name);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011305 window->setTouchable(false);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011306 window->setTouchOcclusionMode(mode);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011307 window->setAlpha(alpha);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011308 return window;
11309 }
11310
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000011311 sp<FakeWindowHandle> getWindow(gui::Uid uid, std::string name) {
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011312 std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
11313 sp<FakeWindowHandle> window =
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011314 sp<FakeWindowHandle>::make(app, mDispatcher, name, ui::LogicalDisplayId::DEFAULT);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011315 // Generate an arbitrary PID based on the UID
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000011316 window->setOwnerInfo(gui::Pid{static_cast<pid_t>(1777 + (uid.val() % 10000))}, uid);
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011317 return window;
11318 }
11319
11320 void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000011321 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011322 AINPUT_SOURCE_TOUCHSCREEN,
11323 ui::LogicalDisplayId::DEFAULT, points));
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011324 }
11325};
11326
11327TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011328 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011329 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011330 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011331
11332 touch();
11333
11334 mTouchWindow->assertNoEvents();
11335}
11336
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011337TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufino7393d172021-02-26 13:56:11 +000011338 WindowWithBlockUntrustedOcclusionModeWithOpacityBelowThreshold_BlocksTouch) {
11339 const sp<FakeWindowHandle>& w =
11340 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.7f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011341 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011342
11343 touch();
11344
11345 mTouchWindow->assertNoEvents();
11346}
11347
11348TEST_F(InputDispatcherUntrustedTouchesTest,
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011349 WindowWithBlockUntrustedOcclusionMode_DoesNotReceiveTouch) {
11350 const sp<FakeWindowHandle>& w =
11351 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011352 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011353
11354 touch();
11355
11356 w->assertNoEvents();
11357}
11358
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011359TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011360 const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011361 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011362
11363 touch();
11364
11365 mTouchWindow->consumeAnyMotionDown();
11366}
11367
11368TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011369 const sp<FakeWindowHandle>& w =
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011370 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011371 w->setFrame(Rect(0, 0, 50, 50));
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011372 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011373
11374 touch({PointF{100, 100}});
11375
11376 mTouchWindow->consumeAnyMotionDown();
11377}
11378
11379TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011380 const sp<FakeWindowHandle>& w =
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011381 getOccludingWindow(TOUCHED_APP_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011382 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011383
11384 touch();
11385
11386 mTouchWindow->consumeAnyMotionDown();
11387}
11388
11389TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
11390 const sp<FakeWindowHandle>& w =
11391 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011392 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011393
11394 touch();
11395
11396 mTouchWindow->consumeAnyMotionDown();
11397}
11398
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011399TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_DoesNotReceiveTouch) {
11400 const sp<FakeWindowHandle>& w =
11401 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011402 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011403
11404 touch();
11405
11406 w->assertNoEvents();
11407}
11408
11409/**
11410 * This is important to make sure apps can't indirectly learn the position of touches (outside vs
11411 * inside) while letting them pass-through. Note that even though touch passes through the occluding
11412 * window, the occluding window will still receive ACTION_OUTSIDE event.
11413 */
11414TEST_F(InputDispatcherUntrustedTouchesTest,
11415 WindowWithZeroOpacityAndWatchOutside_ReceivesOutsideEvent) {
11416 const sp<FakeWindowHandle>& w =
11417 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011418 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011419 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011420
11421 touch();
11422
11423 w->consumeMotionOutside();
11424}
11425
11426TEST_F(InputDispatcherUntrustedTouchesTest, OutsideEvent_HasZeroCoordinates) {
11427 const sp<FakeWindowHandle>& w =
11428 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080011429 w->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011430 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011431
11432 touch();
11433
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080011434 w->consumeMotionOutsideWithZeroedCoords();
Bernardo Rufinoa43a5a42021-02-17 12:21:14 +000011435}
11436
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011437TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011438 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011439 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11440 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011441 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011442
11443 touch();
11444
11445 mTouchWindow->consumeAnyMotionDown();
11446}
11447
11448TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
11449 const sp<FakeWindowHandle>& w =
11450 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11451 MAXIMUM_OBSCURING_OPACITY);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011452 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011453
11454 touch();
11455
11456 mTouchWindow->consumeAnyMotionDown();
11457}
11458
11459TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011460 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011461 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11462 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011463 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011464
11465 touch();
11466
11467 mTouchWindow->assertNoEvents();
11468}
11469
11470TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
11471 // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
11472 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011473 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11474 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011475 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011476 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11477 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011478 mDispatcher->onWindowInfosChanged(
11479 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011480
11481 touch();
11482
11483 mTouchWindow->assertNoEvents();
11484}
11485
11486TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
11487 // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
11488 const sp<FakeWindowHandle>& w1 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011489 getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY,
11490 OPACITY_FAR_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011491 const sp<FakeWindowHandle>& w2 =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011492 getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY,
11493 OPACITY_FAR_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011494 mDispatcher->onWindowInfosChanged(
11495 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011496
11497 touch();
11498
11499 mTouchWindow->consumeAnyMotionDown();
11500}
11501
11502TEST_F(InputDispatcherUntrustedTouchesTest,
11503 WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
11504 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011505 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11506 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011507 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011508 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11509 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011510 mDispatcher->onWindowInfosChanged(
11511 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011512
11513 touch();
11514
11515 mTouchWindow->consumeAnyMotionDown();
11516}
11517
11518TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
11519 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011520 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11521 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino1d0d1f22021-02-12 15:08:43 +000011522 const sp<FakeWindowHandle>& wC =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011523 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11524 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011525 mDispatcher->onWindowInfosChanged(
11526 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoc3b7b8c2021-01-29 17:38:07 +000011527
11528 touch();
11529
11530 mTouchWindow->assertNoEvents();
11531}
11532
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011533TEST_F(InputDispatcherUntrustedTouchesTest,
11534 WindowWithOpacityAboveThresholdAndSelfWindow_BlocksTouch) {
11535 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011536 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11537 OPACITY_BELOW_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011538 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011539 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11540 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011541 mDispatcher->onWindowInfosChanged(
11542 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011543
11544 touch();
11545
11546 mTouchWindow->assertNoEvents();
11547}
11548
11549TEST_F(InputDispatcherUntrustedTouchesTest,
11550 WindowWithOpacityBelowThresholdAndSelfWindow_AllowsTouch) {
11551 const sp<FakeWindowHandle>& wA =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011552 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11553 OPACITY_ABOVE_THRESHOLD);
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011554 const sp<FakeWindowHandle>& wB =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011555 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11556 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011557 mDispatcher->onWindowInfosChanged(
11558 {{*wA->getInfo(), *wB->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011559
11560 touch();
11561
11562 mTouchWindow->consumeAnyMotionDown();
11563}
11564
11565TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithOpacityAboveThreshold_AllowsTouch) {
11566 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011567 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::USE_OPACITY,
11568 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011569 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011570
11571 touch();
11572
11573 mTouchWindow->consumeAnyMotionDown();
11574}
11575
11576TEST_F(InputDispatcherUntrustedTouchesTest, SelfWindowWithBlockUntrustedMode_AllowsTouch) {
11577 const sp<FakeWindowHandle>& w =
11578 getOccludingWindow(TOUCHED_APP_UID, "T", TouchOcclusionMode::BLOCK_UNTRUSTED);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011579 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino6d52e542021-02-15 18:38:10 +000011580
11581 touch();
11582
11583 mTouchWindow->consumeAnyMotionDown();
11584}
11585
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011586TEST_F(InputDispatcherUntrustedTouchesTest,
11587 OpacityThresholdIs0AndWindowAboveThreshold_BlocksTouch) {
11588 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11589 const sp<FakeWindowHandle>& w =
11590 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.1f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011591 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011592
11593 touch();
11594
11595 mTouchWindow->assertNoEvents();
11596}
11597
11598TEST_F(InputDispatcherUntrustedTouchesTest, OpacityThresholdIs0AndWindowAtThreshold_AllowsTouch) {
11599 mDispatcher->setMaximumObscuringOpacityForTouch(0.0f);
11600 const sp<FakeWindowHandle>& w =
11601 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.0f);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011602 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011603
11604 touch();
11605
11606 mTouchWindow->consumeAnyMotionDown();
11607}
11608
11609TEST_F(InputDispatcherUntrustedTouchesTest,
11610 OpacityThresholdIs1AndWindowBelowThreshold_AllowsTouch) {
11611 mDispatcher->setMaximumObscuringOpacityForTouch(1.0f);
11612 const sp<FakeWindowHandle>& w =
Bernardo Rufino7393d172021-02-26 13:56:11 +000011613 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11614 OPACITY_ABOVE_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011615 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011616
11617 touch();
11618
11619 mTouchWindow->consumeAnyMotionDown();
11620}
11621
11622TEST_F(InputDispatcherUntrustedTouchesTest,
11623 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromSameApp_BlocksTouch) {
11624 const sp<FakeWindowHandle>& w1 =
11625 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11626 OPACITY_BELOW_THRESHOLD);
11627 const sp<FakeWindowHandle>& w2 =
11628 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
11629 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011630 mDispatcher->onWindowInfosChanged(
11631 {{*w1->getInfo(), *w2->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011632
11633 touch();
11634
11635 mTouchWindow->assertNoEvents();
11636}
11637
11638/**
11639 * Window B of BLOCK_UNTRUSTED occlusion mode is enough to block the touch, we're testing that the
11640 * addition of another window (C) of USE_OPACITY occlusion mode and opacity below the threshold
11641 * (which alone would result in allowing touches) does not affect the blocking behavior.
11642 */
11643TEST_F(InputDispatcherUntrustedTouchesTest,
11644 WindowWithBlockUntrustedModeAndWindowWithOpacityBelowFromDifferentApps_BlocksTouch) {
11645 const sp<FakeWindowHandle>& wB =
11646 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED,
11647 OPACITY_BELOW_THRESHOLD);
11648 const sp<FakeWindowHandle>& wC =
11649 getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY,
11650 OPACITY_BELOW_THRESHOLD);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011651 mDispatcher->onWindowInfosChanged(
11652 {{*wB->getInfo(), *wC->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufino7393d172021-02-26 13:56:11 +000011653
11654 touch();
11655
11656 mTouchWindow->assertNoEvents();
11657}
11658
11659/**
11660 * This test is testing that a window from a different UID but with same application token doesn't
11661 * block the touch. Apps can share the application token for close UI collaboration for example.
11662 */
11663TEST_F(InputDispatcherUntrustedTouchesTest,
11664 WindowWithSameApplicationTokenFromDifferentApp_AllowsTouch) {
11665 const sp<FakeWindowHandle>& w =
11666 getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
11667 w->setApplicationToken(mTouchWindow->getApplicationToken());
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011668 mDispatcher->onWindowInfosChanged({{*w->getInfo(), *mTouchWindow->getInfo()}, {}, 0, 0});
Bernardo Rufinoccd3dd62021-02-15 18:47:42 +000011669
11670 touch();
11671
11672 mTouchWindow->consumeAnyMotionDown();
11673}
11674
arthurhungb89ccb02020-12-30 16:19:01 +080011675class InputDispatcherDragTests : public InputDispatcherTest {
11676protected:
11677 std::shared_ptr<FakeApplicationHandle> mApp;
11678 sp<FakeWindowHandle> mWindow;
11679 sp<FakeWindowHandle> mSecondWindow;
11680 sp<FakeWindowHandle> mDragWindow;
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011681 sp<FakeWindowHandle> mSpyWindow;
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011682 // Mouse would force no-split, set the id as non-zero to verify if drag state could track it.
11683 static constexpr int32_t MOUSE_POINTER_ID = 1;
arthurhungb89ccb02020-12-30 16:19:01 +080011684
11685 void SetUp() override {
11686 InputDispatcherTest::SetUp();
11687 mApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011688 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
11689 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011690 mWindow->setFrame(Rect(0, 0, 100, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011691
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011692 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
11693 ui::LogicalDisplayId::DEFAULT);
arthurhungb89ccb02020-12-30 16:19:01 +080011694 mSecondWindow->setFrame(Rect(100, 0, 200, 100));
arthurhungb89ccb02020-12-30 16:19:01 +080011695
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011696 mSpyWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "SpyWindow",
11697 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011698 mSpyWindow->setSpy(true);
11699 mSpyWindow->setTrustedOverlay(true);
11700 mSpyWindow->setFrame(Rect(0, 0, 200, 100));
11701
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011702 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011703 mDispatcher->onWindowInfosChanged(
11704 {{*mSpyWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()},
11705 {},
11706 0,
11707 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011708 }
11709
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011710 void injectDown(int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
11711 switch (fromSource) {
11712 case AINPUT_SOURCE_TOUCHSCREEN:
11713 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011714 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011715 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011716 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11717 break;
11718 case AINPUT_SOURCE_STYLUS:
11719 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011720 injectMotionEvent(*mDispatcher,
11721 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11722 AINPUT_SOURCE_STYLUS)
11723 .buttonState(
11724 AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
11725 .pointer(PointerBuilder(0, ToolType::STYLUS)
11726 .x(50)
11727 .y(50))
11728 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011729 break;
11730 case AINPUT_SOURCE_MOUSE:
11731 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011732 injectMotionEvent(*mDispatcher,
11733 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
11734 AINPUT_SOURCE_MOUSE)
11735 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
11736 .pointer(PointerBuilder(MOUSE_POINTER_ID,
11737 ToolType::MOUSE)
11738 .x(50)
11739 .y(50))
11740 .build()));
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011741 break;
11742 default:
11743 FAIL() << "Source " << fromSource << " doesn't support drag and drop";
11744 }
arthurhungb89ccb02020-12-30 16:19:01 +080011745
11746 // Window should receive motion event.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011747 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011748 // Spy window should also receive motion event
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011749 mSpyWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000011750 }
11751
11752 // Start performing drag, we will create a drag window and transfer touch to it.
11753 // @param sendDown : if true, send a motion down on first window before perform drag and drop.
11754 // Returns true on success.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011755 bool startDrag(bool sendDown = true, int fromSource = AINPUT_SOURCE_TOUCHSCREEN) {
Arthur Hung54745652022-04-20 07:17:41 +000011756 if (sendDown) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011757 injectDown(fromSource);
Arthur Hung54745652022-04-20 07:17:41 +000011758 }
arthurhungb89ccb02020-12-30 16:19:01 +080011759
11760 // The drag window covers the entire display
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011761 mDragWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "DragWindow",
11762 ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011763 mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011764 mDispatcher->onWindowInfosChanged({{*mDragWindow->getInfo(), *mSpyWindow->getInfo(),
11765 *mWindow->getInfo(), *mSecondWindow->getInfo()},
11766 {},
11767 0,
11768 0});
arthurhungb89ccb02020-12-30 16:19:01 +080011769
11770 // Transfer touch focus to the drag window
Arthur Hung54745652022-04-20 07:17:41 +000011771 bool transferred =
Prabir Pradhan367f3432024-02-13 23:05:58 +000011772 mDispatcher->transferTouchGesture(mWindow->getToken(), mDragWindow->getToken(),
11773 /*isDragDrop=*/true);
Arthur Hung54745652022-04-20 07:17:41 +000011774 if (transferred) {
11775 mWindow->consumeMotionCancel();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011776 mDragWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
11777 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000011778 }
11779 return transferred;
arthurhungb89ccb02020-12-30 16:19:01 +080011780 }
11781};
11782
11783TEST_F(InputDispatcherDragTests, DragEnterAndDragExit) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011784 startDrag();
arthurhungb89ccb02020-12-30 16:19:01 +080011785
11786 // Move on window.
11787 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011788 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011789 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011790 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011791 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11792 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011793 mWindow->consumeDragEvent(false, 50, 50);
11794 mSecondWindow->assertNoEvents();
11795
11796 // Move to another window.
11797 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011798 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011799 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011800 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011801 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11802 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011803 mWindow->consumeDragEvent(true, 150, 50);
11804 mSecondWindow->consumeDragEvent(false, 50, 50);
11805
11806 // Move back to original window.
11807 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011808 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011809 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011810 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011811 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11812 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011813 mWindow->consumeDragEvent(false, 50, 50);
11814 mSecondWindow->consumeDragEvent(true, -50, 50);
11815
11816 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011817 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011818 {50, 50}))
arthurhungb89ccb02020-12-30 16:19:01 +080011819 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011820 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungb89ccb02020-12-30 16:19:01 +080011821 mWindow->assertNoEvents();
11822 mSecondWindow->assertNoEvents();
11823}
11824
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011825TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011826 startDrag();
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011827
11828 // No cancel event after drag start
11829 mSpyWindow->assertNoEvents();
11830
11831 const MotionEvent secondFingerDownEvent =
11832 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11833 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011834 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11835 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011836 .build();
11837 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011838 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari6abcf8f2022-06-06 10:08:05 +000011839 InputEventInjectionSync::WAIT_FOR_RESULT))
11840 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11841
11842 // Receives cancel for first pointer after next pointer down
11843 mSpyWindow->consumeMotionCancel();
11844 mSpyWindow->consumeMotionDown();
11845
11846 mSpyWindow->assertNoEvents();
11847}
11848
arthurhungf452d0b2021-01-06 00:19:52 +080011849TEST_F(InputDispatcherDragTests, DragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011850 startDrag();
arthurhungf452d0b2021-01-06 00:19:52 +080011851
11852 // Move on window.
11853 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011854 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011855 ui::LogicalDisplayId::DEFAULT, {50, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080011856 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011857 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11858 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080011859 mWindow->consumeDragEvent(false, 50, 50);
11860 mSecondWindow->assertNoEvents();
11861
11862 // Move to another window.
11863 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011864 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011865 ui::LogicalDisplayId::DEFAULT, {150, 50}))
arthurhungf452d0b2021-01-06 00:19:52 +080011866 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011867 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11868 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhungf452d0b2021-01-06 00:19:52 +080011869 mWindow->consumeDragEvent(true, 150, 50);
11870 mSecondWindow->consumeDragEvent(false, 50, 50);
11871
11872 // drop to another window.
11873 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011874 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
arthurhungf452d0b2021-01-06 00:19:52 +080011875 {150, 50}))
11876 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011877 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011878 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhungf452d0b2021-01-06 00:19:52 +080011879 mWindow->assertNoEvents();
11880 mSecondWindow->assertNoEvents();
11881}
11882
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011883TEST_F(InputDispatcherDragTests, DragAndDropNotCancelledIfSomeOtherPointerIsPilfered) {
11884 startDrag();
11885
11886 // No cancel event after drag start
11887 mSpyWindow->assertNoEvents();
11888
11889 const MotionEvent secondFingerDownEvent =
11890 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
11891 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
11892 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
11893 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
11894 .build();
11895 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
11896 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
11897 InputEventInjectionSync::WAIT_FOR_RESULT))
11898 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11899
11900 // Receives cancel for first pointer after next pointer down
11901 mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
Siarhei Vishniakou1ff00cc2023-12-13 16:12:13 -080011902 mSpyWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithPointerIds({1})));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011903 mDragWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
11904
11905 mSpyWindow->assertNoEvents();
11906
11907 // Spy window calls pilfer pointers
11908 EXPECT_EQ(OK, mDispatcher->pilferPointers(mSpyWindow->getToken()));
11909 mDragWindow->assertNoEvents();
11910
11911 const MotionEvent firstFingerMoveEvent =
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080011912 MotionEventBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011913 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
11914 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(60).y(60))
11915 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(60).y(60))
11916 .build();
11917 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakou96a15572023-12-18 10:47:52 -080011918 injectMotionEvent(*mDispatcher, firstFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011919 InputEventInjectionSync::WAIT_FOR_RESULT))
11920 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
11921
11922 // Drag window should still receive the new event
Prabir Pradhan65455c72024-02-13 21:46:41 +000011923 mDragWindow->consumeMotionEvent(
11924 AllOf(WithMotionAction(ACTION_MOVE), WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
Vaibhav Devmurari110ba322023-11-17 10:47:16 +000011925 mDragWindow->assertNoEvents();
11926}
11927
arthurhung6d4bed92021-03-17 11:59:33 +080011928TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011929 startDrag(true, AINPUT_SOURCE_STYLUS);
arthurhung6d4bed92021-03-17 11:59:33 +080011930
11931 // Move on window and keep button pressed.
11932 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011933 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011934 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11935 .buttonState(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011936 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011937 .build()))
11938 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011939 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11940 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011941 mWindow->consumeDragEvent(false, 50, 50);
11942 mSecondWindow->assertNoEvents();
11943
11944 // Move to another window and release button, expect to drop item.
11945 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011946 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011947 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
11948 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011949 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011950 .build()))
11951 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011952 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11953 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011954 mWindow->assertNoEvents();
11955 mSecondWindow->assertNoEvents();
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070011956 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
arthurhung6d4bed92021-03-17 11:59:33 +080011957
11958 // nothing to the window.
11959 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011960 injectMotionEvent(*mDispatcher,
arthurhung6d4bed92021-03-17 11:59:33 +080011961 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_STYLUS)
11962 .buttonState(0)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070011963 .pointer(PointerBuilder(0, ToolType::STYLUS).x(150).y(50))
arthurhung6d4bed92021-03-17 11:59:33 +080011964 .build()))
11965 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011966 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
arthurhung6d4bed92021-03-17 11:59:33 +080011967 mWindow->assertNoEvents();
11968 mSecondWindow->assertNoEvents();
11969}
11970
Arthur Hung54745652022-04-20 07:17:41 +000011971TEST_F(InputDispatcherDragTests, DragAndDropOnInvalidWindow) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000011972 startDrag();
Arthur Hung6d0571e2021-04-09 20:18:16 +080011973
11974 // Set second window invisible.
11975 mSecondWindow->setVisible(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070011976 mDispatcher->onWindowInfosChanged(
11977 {{*mDragWindow->getInfo(), *mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
Arthur Hung6d0571e2021-04-09 20:18:16 +080011978
11979 // Move on window.
11980 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011981 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011982 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080011983 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011984 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11985 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011986 mWindow->consumeDragEvent(false, 50, 50);
11987 mSecondWindow->assertNoEvents();
11988
11989 // Move to another window.
11990 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070011991 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011992 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung6d0571e2021-04-09 20:18:16 +080011993 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070011994 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
11995 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung6d0571e2021-04-09 20:18:16 +080011996 mWindow->consumeDragEvent(true, 150, 50);
11997 mSecondWindow->assertNoEvents();
11998
11999 // drop to another window.
12000 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012001 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung6d0571e2021-04-09 20:18:16 +080012002 {150, 50}))
12003 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012004 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012005 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
Arthur Hung6d0571e2021-04-09 20:18:16 +080012006 mWindow->assertNoEvents();
12007 mSecondWindow->assertNoEvents();
12008}
12009
Arthur Hung54745652022-04-20 07:17:41 +000012010TEST_F(InputDispatcherDragTests, NoDragAndDropWhenMultiFingers) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012011 // Ensure window could track pointerIds if it didn't support split touch.
12012 mWindow->setPreventSplitting(true);
12013
Arthur Hung54745652022-04-20 07:17:41 +000012014 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012015 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12016 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000012017 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012018 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012019
12020 const MotionEvent secondFingerDownEvent =
12021 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012022 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000012023 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012024 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12025 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(75).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012026 .build();
12027 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012028 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012029 InputEventInjectionSync::WAIT_FOR_RESULT))
12030 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000012031 mWindow->consumeMotionPointerDown(/*pointerIndex=*/1);
Arthur Hung54745652022-04-20 07:17:41 +000012032
12033 // Should not perform drag and drop when window has multi fingers.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012034 ASSERT_FALSE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000012035}
12036
12037TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouch) {
12038 // First down on second window.
12039 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012040 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12041 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung54745652022-04-20 07:17:41 +000012042 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12043
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012044 mSecondWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012045
12046 // Second down on first window.
12047 const MotionEvent secondFingerDownEvent =
12048 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012049 .displayId(ui::LogicalDisplayId::DEFAULT)
Arthur Hung54745652022-04-20 07:17:41 +000012050 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012051 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12052 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012053 .build();
12054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012055 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012056 InputEventInjectionSync::WAIT_FOR_RESULT))
12057 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012058 mWindow->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
12059 mSecondWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT);
Arthur Hung54745652022-04-20 07:17:41 +000012060
12061 // Perform drag and drop from first window.
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012062 ASSERT_TRUE(startDrag(false));
Arthur Hung54745652022-04-20 07:17:41 +000012063
12064 // Move on window.
12065 const MotionEvent secondFingerMoveEvent =
12066 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12067 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012068 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12069 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012070 .build();
12071 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012072 injectMotionEvent(*mDispatcher, secondFingerMoveEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012073 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012074 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12075 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung54745652022-04-20 07:17:41 +000012076 mWindow->consumeDragEvent(false, 50, 50);
12077 mSecondWindow->consumeMotionMove();
12078
12079 // Release the drag pointer should perform drop.
12080 const MotionEvent secondFingerUpEvent =
12081 MotionEventBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12082 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012083 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12084 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Arthur Hung54745652022-04-20 07:17:41 +000012085 .build();
12086 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012087 injectMotionEvent(*mDispatcher, secondFingerUpEvent, INJECT_EVENT_TIMEOUT,
Arthur Hung54745652022-04-20 07:17:41 +000012088 InputEventInjectionSync::WAIT_FOR_RESULT));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012089 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012090 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
Arthur Hung54745652022-04-20 07:17:41 +000012091 mWindow->assertNoEvents();
12092 mSecondWindow->consumeMotionMove();
12093}
12094
Arthur Hung3915c1f2022-05-31 07:17:17 +000012095TEST_F(InputDispatcherDragTests, DragAndDropWhenMultiDisplays) {
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012096 startDrag();
Arthur Hung3915c1f2022-05-31 07:17:17 +000012097
12098 // Update window of second display.
12099 sp<FakeWindowHandle> windowInSecondary =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012100 sp<FakeWindowHandle>::make(mApp, mDispatcher, "D_2", SECOND_DISPLAY_ID);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012101 mDispatcher->onWindowInfosChanged(
12102 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12103 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12104 {},
12105 0,
12106 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012107
12108 // Let second display has a touch state.
12109 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012110 injectMotionEvent(*mDispatcher,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012111 MotionEventBuilder(AMOTION_EVENT_ACTION_DOWN,
12112 AINPUT_SOURCE_TOUCHSCREEN)
12113 .displayId(SECOND_DISPLAY_ID)
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012114 .pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012115 .build()));
Prabir Pradhan7662a8d2023-12-15 01:58:14 +000012116 windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID, /*expectedFlag=*/0);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012117 // Update window again.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012118 mDispatcher->onWindowInfosChanged(
12119 {{*mDragWindow->getInfo(), *mSpyWindow->getInfo(), *mWindow->getInfo(),
12120 *mSecondWindow->getInfo(), *windowInSecondary->getInfo()},
12121 {},
12122 0,
12123 0});
Arthur Hung3915c1f2022-05-31 07:17:17 +000012124
12125 // Move on window.
12126 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012127 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012128 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012129 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012130 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12131 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012132 mWindow->consumeDragEvent(false, 50, 50);
12133 mSecondWindow->assertNoEvents();
12134
12135 // Move to another window.
12136 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012137 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012138 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Arthur Hung3915c1f2022-05-31 07:17:17 +000012139 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012140 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12141 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hung3915c1f2022-05-31 07:17:17 +000012142 mWindow->consumeDragEvent(true, 150, 50);
12143 mSecondWindow->consumeDragEvent(false, 50, 50);
12144
12145 // drop to another window.
12146 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012147 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Arthur Hung3915c1f2022-05-31 07:17:17 +000012148 {150, 50}))
12149 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012150 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012151 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hung3915c1f2022-05-31 07:17:17 +000012152 mWindow->assertNoEvents();
12153 mSecondWindow->assertNoEvents();
12154}
12155
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012156TEST_F(InputDispatcherDragTests, MouseDragAndDrop) {
12157 startDrag(true, AINPUT_SOURCE_MOUSE);
12158 // Move on window.
12159 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012160 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012161 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12162 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012163 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012164 .x(50)
12165 .y(50))
12166 .build()))
12167 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012168 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12169 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012170 mWindow->consumeDragEvent(false, 50, 50);
12171 mSecondWindow->assertNoEvents();
12172
12173 // Move to another window.
12174 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012175 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012176 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_MOUSE)
12177 .buttonState(AMOTION_EVENT_BUTTON_PRIMARY)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012178 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012179 .x(150)
12180 .y(50))
12181 .build()))
12182 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012183 mDragWindow->consumeMotionMove(ui::LogicalDisplayId::DEFAULT,
12184 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012185 mWindow->consumeDragEvent(true, 150, 50);
12186 mSecondWindow->consumeDragEvent(false, 50, 50);
12187
12188 // drop to another window.
12189 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012190 injectMotionEvent(*mDispatcher,
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012191 MotionEventBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_MOUSE)
12192 .buttonState(0)
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012193 .pointer(PointerBuilder(MOUSE_POINTER_ID, ToolType::MOUSE)
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012194 .x(150)
12195 .y(50))
12196 .build()))
12197 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012198 mDragWindow->consumeMotionUp(ui::LogicalDisplayId::DEFAULT, AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE);
Siarhei Vishniakoua66d65e2023-06-16 10:32:51 -070012199 mFakePolicy->assertDropTargetEquals(*mDispatcher, mSecondWindow->getToken());
Arthur Hungb75c2aa2022-07-15 09:35:36 +000012200 mWindow->assertNoEvents();
12201 mSecondWindow->assertNoEvents();
12202}
12203
Linnan Li5af92f92023-07-14 14:36:22 +080012204/**
12205 * Start drag and drop with a pointer whose id is not 0, cancel the current touch, and ensure drag
12206 * and drop is also canceled. Then inject a simple gesture, and ensure dispatcher does not crash.
12207 */
12208TEST_F(InputDispatcherDragTests, DragAndDropFinishedWhenCancelCurrentTouch) {
12209 // Down on second window
12210 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012211 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12212 ui::LogicalDisplayId::DEFAULT, {150, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012213 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12214
12215 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionDown());
12216 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionDown());
12217
12218 // Down on first window
12219 const MotionEvent secondFingerDownEvent =
12220 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012221 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012222 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(50))
12223 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
12224 .build();
12225 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12226 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
12227 InputEventInjectionSync::WAIT_FOR_RESULT))
12228 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12229 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12230 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionMove());
12231 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionPointerDown(1));
12232
12233 // Start drag on first window
12234 ASSERT_TRUE(startDrag(/*sendDown=*/false, AINPUT_SOURCE_TOUCHSCREEN));
12235
12236 // Trigger cancel
12237 mDispatcher->cancelCurrentTouch();
12238 ASSERT_NO_FATAL_FAILURE(mSecondWindow->consumeMotionCancel());
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012239 ASSERT_NO_FATAL_FAILURE(mDragWindow->consumeMotionCancel(ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan65455c72024-02-13 21:46:41 +000012240 AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE));
Linnan Li5af92f92023-07-14 14:36:22 +080012241 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionCancel());
12242
12243 ASSERT_TRUE(mDispatcher->waitForIdle());
12244 // The D&D finished with nullptr
12245 mFakePolicy->assertDropTargetEquals(*mDispatcher, nullptr);
12246
12247 // Remove drag window
12248 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo(), *mSecondWindow->getInfo()}, {}, 0, 0});
12249
12250 // Inject a simple gesture, ensure dispatcher not crashed
12251 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012252 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12253 ui::LogicalDisplayId::DEFAULT, PointF{50, 50}))
Linnan Li5af92f92023-07-14 14:36:22 +080012254 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12255 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionDown());
12256
12257 const MotionEvent moveEvent =
12258 MotionEventBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012259 .displayId(ui::LogicalDisplayId::DEFAULT)
Linnan Li5af92f92023-07-14 14:36:22 +080012260 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12261 .build();
12262 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12263 injectMotionEvent(*mDispatcher, moveEvent, INJECT_EVENT_TIMEOUT,
12264 InputEventInjectionSync::WAIT_FOR_RESULT))
12265 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12266 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionMove());
12267
12268 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012269 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ui::LogicalDisplayId::DEFAULT,
Linnan Li5af92f92023-07-14 14:36:22 +080012270 {50, 50}))
12271 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12272 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionUp());
12273}
12274
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012275TEST_F(InputDispatcherDragTests, NoDragAndDropWithHoveringPointer) {
12276 // Start hovering over the window.
12277 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
12278 injectMotionEvent(*mDispatcher, ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012279 ui::LogicalDisplayId::DEFAULT, {50, 50}));
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000012280
12281 ASSERT_NO_FATAL_FAILURE(mWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12282 ASSERT_NO_FATAL_FAILURE(mSpyWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER)));
12283
12284 ASSERT_FALSE(startDrag(/*sendDown=*/false))
12285 << "Drag and drop should not work with a hovering pointer";
12286}
12287
Linnan Lia512a532024-10-08 16:19:16 +080012288/**
12289 * Two devices, we use the second pointer of Device A to start the drag, during the drag process, if
12290 * we perform a click using Device B, the dispatcher should work well.
12291 */
12292TEST_F(InputDispatcherDragTests, DragAndDropWhenSplitTouchAndMultiDevice) {
12293 const DeviceId deviceA = 1;
12294 const DeviceId deviceB = 2;
12295 // First down on second window with deviceA.
12296 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12297 .deviceId(deviceA)
12298 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
12299 .build());
12300 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA),
12301 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12302
12303 // Second down on first window with deviceA
12304 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
12305 .deviceId(deviceA)
12306 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
12307 .pointer(PointerBuilder(1, ToolType::FINGER).x(50).y(50))
12308 .build());
12309 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA),
12310 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12311 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12312 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12313
12314 // Perform drag and drop from first window.
12315 ASSERT_TRUE(startDrag(/*sendDown=*/false));
12316
12317 // Click first window with device B, we should ensure dispatcher work well.
12318 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_MOUSE)
12319 .deviceId(deviceB)
12320 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
12321 .build());
12322 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB),
12323 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12324
12325 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_MOUSE)
12326 .deviceId(deviceB)
12327 .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
12328 .build());
12329 mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB),
12330 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12331
12332 // Move with device A.
12333 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
12334 .deviceId(deviceA)
12335 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
12336 .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51))
12337 .build());
12338
12339 mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12340 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
12341 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
12342 mWindow->consumeDragEvent(false, 51, 51);
12343 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12344 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12345
12346 // Releasing the drag pointer should cause drop.
12347 mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
12348 .deviceId(deviceA)
12349 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
12350 .pointer(PointerBuilder(1, ToolType::FINGER).x(51).y(51))
12351 .build());
12352 mDragWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA),
12353 WithDisplayId(ui::LogicalDisplayId::DEFAULT),
12354 WithFlags(AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE)));
12355 mFakePolicy->assertDropTargetEquals(*mDispatcher, mWindow->getToken());
12356 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(deviceA),
12357 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12358
12359 // Release all pointers.
12360 mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
12361 .deviceId(deviceA)
12362 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(51))
12363 .build());
12364 mSecondWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA),
12365 WithDisplayId(ui::LogicalDisplayId::DEFAULT)));
12366 mWindow->assertNoEvents();
12367}
12368
Vishnu Nair062a8672021-09-03 16:07:44 -070012369class InputDispatcherDropInputFeatureTest : public InputDispatcherTest {};
12370
12371TEST_F(InputDispatcherDropInputFeatureTest, WindowDropsInput) {
12372 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012373 sp<FakeWindowHandle> window =
12374 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12375 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012376 window->setDropInput(true);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012377 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012378 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012379 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012380 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012381 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012382
12383 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012384 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012385 window->assertNoEvents();
12386
Prabir Pradhan678438e2023-04-13 19:32:51 +000012387 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012388 AINPUT_SOURCE_TOUCHSCREEN,
12389 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012390 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012391 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakoud908f5a2023-11-16 10:25:12 -080012392 mDispatcher->waitForIdle();
Vishnu Nair062a8672021-09-03 16:07:44 -070012393 window->assertNoEvents();
12394
12395 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012396 window->setDropInput(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012397 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012398
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012399 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12400 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012401
Prabir Pradhan678438e2023-04-13 19:32:51 +000012402 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012403 AINPUT_SOURCE_TOUCHSCREEN,
12404 ui::LogicalDisplayId::DEFAULT));
12405 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012406 window->assertNoEvents();
12407}
12408
12409TEST_F(InputDispatcherDropInputFeatureTest, ObscuredWindowDropsInput) {
12410 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12411 std::make_shared<FakeApplicationHandle>();
12412 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012413 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012414 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012415 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012416 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012417 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012418 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012419 sp<FakeWindowHandle> window =
12420 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12421 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012422 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012423 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012424 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012425 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012426 mDispatcher->onWindowInfosChanged(
12427 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012428 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012429 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012430
12431 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012432 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012433 window->assertNoEvents();
12434
Prabir Pradhan678438e2023-04-13 19:32:51 +000012435 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012436 AINPUT_SOURCE_TOUCHSCREEN,
12437 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012438 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012439 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012440 window->assertNoEvents();
12441
12442 // With the flag cleared, the window should get input
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012443 window->setDropInputIfObscured(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012444 mDispatcher->onWindowInfosChanged(
12445 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012446
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012447 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12448 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012449
Prabir Pradhan678438e2023-04-13 19:32:51 +000012450 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012451 AINPUT_SOURCE_TOUCHSCREEN,
12452 ui::LogicalDisplayId::DEFAULT));
12453 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT,
12454 AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED);
Vishnu Nair062a8672021-09-03 16:07:44 -070012455 window->assertNoEvents();
12456}
12457
12458TEST_F(InputDispatcherDropInputFeatureTest, UnobscuredWindowGetsInput) {
12459 std::shared_ptr<FakeApplicationHandle> obscuringApplication =
12460 std::make_shared<FakeApplicationHandle>();
12461 sp<FakeWindowHandle> obscuringWindow =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012462 sp<FakeWindowHandle>::make(obscuringApplication, mDispatcher, "obscuringWindow",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012463 ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012464 obscuringWindow->setFrame(Rect(0, 0, 50, 50));
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012465 obscuringWindow->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012466 obscuringWindow->setTouchable(false);
Vishnu Nair062a8672021-09-03 16:07:44 -070012467 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012468 sp<FakeWindowHandle> window =
12469 sp<FakeWindowHandle>::make(application, mDispatcher, "Test window",
12470 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012471 window->setDropInputIfObscured(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012472 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012473 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Vishnu Nair062a8672021-09-03 16:07:44 -070012474 window->setFocusable(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012475 mDispatcher->onWindowInfosChanged(
12476 {{*obscuringWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012477 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000012478 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Vishnu Nair062a8672021-09-03 16:07:44 -070012479
12480 // With the flag set, window should not get any input
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012481 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012482 window->assertNoEvents();
12483
Prabir Pradhan678438e2023-04-13 19:32:51 +000012484 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012485 AINPUT_SOURCE_TOUCHSCREEN,
12486 ui::LogicalDisplayId::DEFAULT));
Siarhei Vishniakou5c02a712023-05-15 15:45:02 -070012487 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012488 ui::LogicalDisplayId::DEFAULT));
Vishnu Nair062a8672021-09-03 16:07:44 -070012489 window->assertNoEvents();
12490
12491 // When the window is no longer obscured because it went on top, it should get input
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012492 mDispatcher->onWindowInfosChanged(
12493 {{*window->getInfo(), *obscuringWindow->getInfo()}, {}, 0, 0});
Vishnu Nair062a8672021-09-03 16:07:44 -070012494
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012495 mDispatcher->notifyKey(generateKeyArgs(AKEY_EVENT_ACTION_UP, ui::LogicalDisplayId::DEFAULT));
12496 window->consumeKeyUp(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012497
Prabir Pradhan678438e2023-04-13 19:32:51 +000012498 mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012499 AINPUT_SOURCE_TOUCHSCREEN,
12500 ui::LogicalDisplayId::DEFAULT));
12501 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vishnu Nair062a8672021-09-03 16:07:44 -070012502 window->assertNoEvents();
12503}
12504
Antonio Kantekf16f2832021-09-28 04:39:20 +000012505class InputDispatcherTouchModeChangedTests : public InputDispatcherTest {
12506protected:
12507 std::shared_ptr<FakeApplicationHandle> mApp;
Antonio Kantek15beb512022-06-13 22:35:41 +000012508 std::shared_ptr<FakeApplicationHandle> mSecondaryApp;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012509 sp<FakeWindowHandle> mWindow;
12510 sp<FakeWindowHandle> mSecondWindow;
Antonio Kantek15beb512022-06-13 22:35:41 +000012511 sp<FakeWindowHandle> mThirdWindow;
Antonio Kantekf16f2832021-09-28 04:39:20 +000012512
12513 void SetUp() override {
12514 InputDispatcherTest::SetUp();
12515
12516 mApp = std::make_shared<FakeApplicationHandle>();
Antonio Kantek15beb512022-06-13 22:35:41 +000012517 mSecondaryApp = std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012518 mWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow",
12519 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012520 mWindow->setFocusable(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012521 setFocusedWindow(mWindow);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012522 mSecondWindow = sp<FakeWindowHandle>::make(mApp, mDispatcher, "TestWindow2",
12523 ui::LogicalDisplayId::DEFAULT);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012524 mSecondWindow->setFocusable(true);
Antonio Kantek15beb512022-06-13 22:35:41 +000012525 mThirdWindow =
12526 sp<FakeWindowHandle>::make(mSecondaryApp, mDispatcher,
12527 "TestWindow3_SecondaryDisplay", SECOND_DISPLAY_ID);
12528 mThirdWindow->setFocusable(true);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012529
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012530 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, mApp);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012531 mDispatcher->onWindowInfosChanged(
12532 {{*mWindow->getInfo(), *mSecondWindow->getInfo(), *mThirdWindow->getInfo()},
12533 {},
12534 0,
12535 0});
Antonio Kantek15beb512022-06-13 22:35:41 +000012536 mThirdWindow->setOwnerInfo(SECONDARY_WINDOW_PID, SECONDARY_WINDOW_UID);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012537 mWindow->consumeFocusEvent(true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012538
Antonio Kantek15beb512022-06-13 22:35:41 +000012539 // Set main display initial touch mode to InputDispatcher::kDefaultInTouchMode.
Prabir Pradhan5735a322022-04-11 17:23:34 +000012540 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012541 WINDOW_UID, /*hasPermission=*/true,
12542 ui::LogicalDisplayId::DEFAULT)) {
Antonio Kantek48710e42022-03-24 14:19:30 -070012543 mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
12544 mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012545 mThirdWindow->assertNoEvents();
12546 }
12547
12548 // Set secondary display initial touch mode to InputDispatcher::kDefaultInTouchMode.
12549 if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, SECONDARY_WINDOW_PID,
Harry Cutts33476232023-01-30 19:57:29 +000012550 SECONDARY_WINDOW_UID, /*hasPermission=*/true,
Antonio Kantek15beb512022-06-13 22:35:41 +000012551 SECOND_DISPLAY_ID)) {
12552 mWindow->assertNoEvents();
12553 mSecondWindow->assertNoEvents();
12554 mThirdWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
Antonio Kantek48710e42022-03-24 14:19:30 -070012555 }
Antonio Kantekf16f2832021-09-28 04:39:20 +000012556 }
12557
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012558 void changeAndVerifyTouchModeInMainDisplayOnly(bool inTouchMode, gui::Pid pid, gui::Uid uid,
Antonio Kantek15beb512022-06-13 22:35:41 +000012559 bool hasPermission) {
Antonio Kanteka042c022022-07-06 16:51:07 -070012560 ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012561 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012562 mWindow->consumeTouchModeEvent(inTouchMode);
12563 mSecondWindow->consumeTouchModeEvent(inTouchMode);
Antonio Kantek15beb512022-06-13 22:35:41 +000012564 mThirdWindow->assertNoEvents();
Antonio Kantekf16f2832021-09-28 04:39:20 +000012565 }
12566};
12567
Antonio Kantek26defcf2022-02-08 01:12:27 +000012568TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012569 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek15beb512022-06-13 22:35:41 +000012570 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode,
12571 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012572 /* hasPermission=*/false);
Antonio Kantekf16f2832021-09-28 04:39:20 +000012573}
12574
Antonio Kantek26defcf2022-02-08 01:12:27 +000012575TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
12576 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012577 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012578 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012579 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012580 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012581 ownerUid, /*hasPermission=*/false,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012582 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek26defcf2022-02-08 01:12:27 +000012583 mWindow->assertNoEvents();
12584 mSecondWindow->assertNoEvents();
12585}
12586
12587TEST_F(InputDispatcherTouchModeChangedTests, NonWindowOwnerMayChangeTouchModeOnPermissionGranted) {
12588 const WindowInfo& windowInfo = *mWindow->getInfo();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012589 gui::Pid ownerPid = windowInfo.ownerPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000012590 gui::Uid ownerUid = windowInfo.ownerUid;
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012591 mWindow->setOwnerInfo(gui::Pid::INVALID, gui::Uid::INVALID);
Antonio Kantek15beb512022-06-13 22:35:41 +000012592 changeAndVerifyTouchModeInMainDisplayOnly(!InputDispatcher::kDefaultInTouchMode, ownerPid,
Harry Cutts33476232023-01-30 19:57:29 +000012593 ownerUid, /*hasPermission=*/true);
Antonio Kantek26defcf2022-02-08 01:12:27 +000012594}
12595
Antonio Kantekf16f2832021-09-28 04:39:20 +000012596TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
Antonio Kantekea47acb2021-12-23 12:41:25 -080012597 const WindowInfo& windowInfo = *mWindow->getInfo();
Antonio Kantek26defcf2022-02-08 01:12:27 +000012598 ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
12599 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012600 /*hasPermission=*/true,
12601 ui::LogicalDisplayId::DEFAULT));
Antonio Kantekf16f2832021-09-28 04:39:20 +000012602 mWindow->assertNoEvents();
12603 mSecondWindow->assertNoEvents();
12604}
12605
Antonio Kantek15beb512022-06-13 22:35:41 +000012606TEST_F(InputDispatcherTouchModeChangedTests, ChangeTouchOnSecondaryDisplayOnly) {
12607 const WindowInfo& windowInfo = *mThirdWindow->getInfo();
12608 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12609 windowInfo.ownerPid, windowInfo.ownerUid,
Harry Cutts33476232023-01-30 19:57:29 +000012610 /*hasPermission=*/true, SECOND_DISPLAY_ID));
Antonio Kantek15beb512022-06-13 22:35:41 +000012611 mWindow->assertNoEvents();
12612 mSecondWindow->assertNoEvents();
12613 mThirdWindow->consumeTouchModeEvent(!InputDispatcher::kDefaultInTouchMode);
12614}
12615
Antonio Kantek48710e42022-03-24 14:19:30 -070012616TEST_F(InputDispatcherTouchModeChangedTests, CanChangeTouchModeWhenOwningLastInteractedWindow) {
12617 // Interact with the window first.
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012618 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012619 injectKeyDown(*mDispatcher, ui::LogicalDisplayId::DEFAULT))
Antonio Kantek48710e42022-03-24 14:19:30 -070012620 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012621 mWindow->consumeKeyDown(ui::LogicalDisplayId::DEFAULT);
Antonio Kantek48710e42022-03-24 14:19:30 -070012622
12623 // Then remove focus.
12624 mWindow->setFocusable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012625 mDispatcher->onWindowInfosChanged({{*mWindow->getInfo()}, {}, 0, 0});
Antonio Kantek48710e42022-03-24 14:19:30 -070012626
12627 // Assert that caller can switch touch mode by owning one of the last interacted window.
12628 const WindowInfo& windowInfo = *mWindow->getInfo();
12629 ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
12630 windowInfo.ownerPid, windowInfo.ownerUid,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012631 /*hasPermission=*/false,
12632 ui::LogicalDisplayId::DEFAULT));
Antonio Kantek48710e42022-03-24 14:19:30 -070012633}
12634
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012635class InputDispatcherSpyWindowTest : public InputDispatcherTest {
12636public:
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012637 sp<FakeWindowHandle> createSpy() {
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012638 std::shared_ptr<FakeApplicationHandle> application =
12639 std::make_shared<FakeApplicationHandle>();
12640 std::string name = "Fake Spy ";
12641 name += std::to_string(mSpyCount++);
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012642 sp<FakeWindowHandle> spy =
12643 sp<FakeWindowHandle>::make(application, mDispatcher, name.c_str(),
12644 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080012645 spy->setSpy(true);
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012646 spy->setTrustedOverlay(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012647 return spy;
12648 }
12649
12650 sp<FakeWindowHandle> createForeground() {
12651 std::shared_ptr<FakeApplicationHandle> application =
12652 std::make_shared<FakeApplicationHandle>();
12653 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070012654 sp<FakeWindowHandle>::make(application, mDispatcher, "Fake Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012655 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012656 window->setFocusable(true);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012657 return window;
12658 }
12659
12660private:
12661 int mSpyCount{0};
12662};
12663
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012664using InputDispatcherSpyWindowDeathTest = InputDispatcherSpyWindowTest;
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012665/**
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012666 * Adding a spy window that is not a trusted overlay causes Dispatcher to abort.
12667 */
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012668TEST_F(InputDispatcherSpyWindowDeathTest, UntrustedSpy_AbortsDispatcher) {
Siarhei Vishniakou21f77bd2023-07-18 17:51:35 -070012669 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080012670 ScopedSilentDeath _silentDeath;
12671
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012672 auto spy = createSpy();
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012673 spy->setTrustedOverlay(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012674 ASSERT_DEATH(mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0}),
Prabir Pradhan5c85e052021-12-22 02:27:12 -080012675 ".* not a trusted overlay");
12676}
12677
12678/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012679 * Input injection into a display with a spy window but no foreground windows should succeed.
12680 */
12681TEST_F(InputDispatcherSpyWindowTest, NoForegroundWindow) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012682 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012683 mDispatcher->onWindowInfosChanged({{*spy->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012684
12685 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012686 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12687 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012688 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012689 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012690}
12691
12692/**
12693 * Verify the order in which different input windows receive events. The touched foreground window
12694 * (if there is one) should always receive the event first. When there are multiple spy windows, the
12695 * spy windows will receive the event according to their Z-order, where the top-most spy window will
12696 * receive events before ones belows it.
12697 *
12698 * Here, we set up a scenario with four windows in the following Z order from the top:
12699 * spy1, spy2, window, spy3.
12700 * We then inject an event and verify that the foreground "window" receives it first, followed by
12701 * "spy1" and "spy2". The "spy3" does not receive the event because it is underneath the foreground
12702 * window.
12703 */
12704TEST_F(InputDispatcherSpyWindowTest, ReceivesInputInOrder) {
12705 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012706 auto spy1 = createSpy();
12707 auto spy2 = createSpy();
12708 auto spy3 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012709 mDispatcher->onWindowInfosChanged(
12710 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo(), *spy3->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012711 const std::vector<sp<FakeWindowHandle>> channels{spy1, spy2, window, spy3};
12712 const size_t numChannels = channels.size();
12713
Michael Wright8e9a8562022-02-09 13:44:29 +000012714 base::unique_fd epollFd(epoll_create1(EPOLL_CLOEXEC));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012715 if (!epollFd.ok()) {
12716 FAIL() << "Failed to create epoll fd";
12717 }
12718
12719 for (size_t i = 0; i < numChannels; i++) {
12720 struct epoll_event event = {.events = EPOLLIN, .data.u64 = i};
12721 if (epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, channels[i]->getChannelFd(), &event) < 0) {
12722 FAIL() << "Failed to add fd to epoll";
12723 }
12724 }
12725
12726 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012727 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12728 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012729 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12730
12731 std::vector<size_t> eventOrder;
12732 std::vector<struct epoll_event> events(numChannels);
12733 for (;;) {
12734 const int nFds = epoll_wait(epollFd.get(), events.data(), static_cast<int>(numChannels),
12735 (100ms).count());
12736 if (nFds < 0) {
12737 FAIL() << "Failed to call epoll_wait";
12738 }
12739 if (nFds == 0) {
12740 break; // epoll_wait timed out
12741 }
12742 for (int i = 0; i < nFds; i++) {
Colin Cross5b799302022-10-18 21:52:41 -070012743 ASSERT_EQ(static_cast<uint32_t>(EPOLLIN), events[i].events);
Siarhei Vishniakou31977182022-09-30 08:51:23 -070012744 eventOrder.push_back(static_cast<size_t>(events[i].data.u64));
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012745 channels[i]->consumeMotionDown();
12746 }
12747 }
12748
12749 // Verify the order in which the events were received.
12750 EXPECT_EQ(3u, eventOrder.size());
12751 EXPECT_EQ(2u, eventOrder[0]); // index 2: window
12752 EXPECT_EQ(0u, eventOrder[1]); // index 0: spy1
12753 EXPECT_EQ(1u, eventOrder[2]); // index 1: spy2
12754}
12755
12756/**
12757 * A spy window using the NOT_TOUCHABLE flag does not receive events.
12758 */
12759TEST_F(InputDispatcherSpyWindowTest, NotTouchable) {
12760 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012761 auto spy = createSpy();
12762 spy->setTouchable(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012763 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012764
12765 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012766 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12767 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012768 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012769 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012770 spy->assertNoEvents();
12771}
12772
12773/**
12774 * A spy window will only receive gestures that originate within its touchable region. Gestures that
12775 * have their ACTION_DOWN outside of the touchable region of the spy window will not be dispatched
12776 * to the window.
12777 */
12778TEST_F(InputDispatcherSpyWindowTest, TouchableRegion) {
12779 auto window = createForeground();
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012780 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012781 spy->setTouchableRegion(Region{{0, 0, 20, 20}});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012782 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012783
12784 // Inject an event outside the spy window's touchable region.
12785 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012786 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12787 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012788 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12789 window->consumeMotionDown();
12790 spy->assertNoEvents();
12791 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012792 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12793 ui::LogicalDisplayId::DEFAULT))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012794 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12795 window->consumeMotionUp();
12796 spy->assertNoEvents();
12797
12798 // Inject an event inside the spy window's touchable region.
12799 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012800 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12801 ui::LogicalDisplayId::DEFAULT, {5, 10}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012802 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12803 window->consumeMotionDown();
12804 spy->consumeMotionDown();
12805}
12806
12807/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012808 * A spy window can listen for touches outside its touchable region using the WATCH_OUTSIDE_TOUCHES
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012809 * flag, but it will get zero-ed out coordinates if the foreground has a different owner.
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012810 */
12811TEST_F(InputDispatcherSpyWindowTest, WatchOutsideTouches) {
12812 auto window = createForeground();
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012813 window->setOwnerInfo(gui::Pid{12}, gui::Uid{34});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012814 auto spy = createSpy();
12815 spy->setWatchOutsideTouch(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000012816 spy->setOwnerInfo(gui::Pid{56}, gui::Uid{78});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012817 spy->setFrame(Rect{0, 0, 20, 20});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012818 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012819
12820 // Inject an event outside the spy window's frame and touchable region.
12821 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012822 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12823 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012824 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12825 window->consumeMotionDown();
Prabir Pradhandfabf8a2022-01-21 08:19:30 -080012826 spy->consumeMotionOutsideWithZeroedCoords();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012827}
12828
12829/**
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012830 * Even when a spy window spans over multiple foreground windows, the spy should receive all
12831 * pointers that are down within its bounds.
12832 */
12833TEST_F(InputDispatcherSpyWindowTest, ReceivesMultiplePointers) {
12834 auto windowLeft = createForeground();
12835 windowLeft->setFrame({0, 0, 100, 200});
12836 auto windowRight = createForeground();
12837 windowRight->setFrame({100, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012838 auto spy = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012839 spy->setFrame({0, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012840 mDispatcher->onWindowInfosChanged(
12841 {{*spy->getInfo(), *windowLeft->getInfo(), *windowRight->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012842
12843 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012844 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12845 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012846 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12847 windowLeft->consumeMotionDown();
12848 spy->consumeMotionDown();
12849
12850 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012851 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012852 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012853 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12854 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012855 .build();
12856 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012857 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012858 InputEventInjectionSync::WAIT_FOR_RESULT))
12859 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12860 windowRight->consumeMotionDown();
Harry Cutts33476232023-01-30 19:57:29 +000012861 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012862}
12863
12864/**
12865 * When the first pointer lands outside the spy window and the second pointer lands inside it, the
12866 * the spy should receive the second pointer with ACTION_DOWN.
12867 */
12868TEST_F(InputDispatcherSpyWindowTest, ReceivesSecondPointerAsDown) {
12869 auto window = createForeground();
12870 window->setFrame({0, 0, 200, 200});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012871 auto spyRight = createSpy();
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012872 spyRight->setFrame({100, 0, 200, 200});
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012873 mDispatcher->onWindowInfosChanged({{*spyRight->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012874
12875 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012876 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12877 ui::LogicalDisplayId::DEFAULT, {50, 50}))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012878 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12879 window->consumeMotionDown();
12880 spyRight->assertNoEvents();
12881
12882 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012883 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012884 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012885 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
12886 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012887 .build();
12888 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012889 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012890 InputEventInjectionSync::WAIT_FOR_RESULT))
12891 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Harry Cutts33476232023-01-30 19:57:29 +000012892 window->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan07e05b62021-11-19 03:57:24 -080012893 spyRight->consumeMotionDown();
12894}
12895
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012896/**
12897 * The spy window should not be able to affect whether or not touches are split. Only the foreground
12898 * windows should be allowed to control split touch.
12899 */
12900TEST_F(InputDispatcherSpyWindowTest, SplitIfNoForegroundWindowTouched) {
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080012901 // This spy window prevents touch splitting. However, we still expect to split touches
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012902 // because a foreground window has not disabled splitting.
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012903 auto spy = createSpy();
Prabir Pradhan76bdecb2022-01-31 11:14:15 -080012904 spy->setPreventSplitting(true);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012905
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012906 auto window = createForeground();
12907 window->setFrame(Rect(0, 0, 100, 100));
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012908
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012909 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012910
12911 // First finger down, no window touched.
12912 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012913 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12914 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012915 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012916 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012917 window->assertNoEvents();
12918
12919 // Second finger down on window, the window should receive touch down.
12920 const MotionEvent secondFingerDownEvent =
Siarhei Vishniakoua16e3a22022-03-02 15:26:40 -080012921 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012922 .displayId(ui::LogicalDisplayId::DEFAULT)
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012923 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070012924 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
12925 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012926 .build();
12927 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012928 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012929 InputEventInjectionSync::WAIT_FOR_RESULT))
12930 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12931
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012932 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Harry Cutts33476232023-01-30 19:57:29 +000012933 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012934}
12935
12936/**
12937 * A spy window will usually be implemented as an un-focusable window. Verify that these windows
12938 * do not receive key events.
12939 */
12940TEST_F(InputDispatcherSpyWindowTest, UnfocusableSpyDoesNotReceiveKeyEvents) {
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080012941 auto spy = createSpy();
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012942 spy->setFocusable(false);
12943
12944 auto window = createForeground();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012945 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012946 setFocusedWindow(window);
12947 window->consumeFocusEvent(true);
12948
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012949 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012950 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012951 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012952
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012953 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyUp(*mDispatcher))
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012954 << "Inject key event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012955 window->consumeKeyUp(ui::LogicalDisplayId::INVALID);
Prabir Pradhan1376fcd2022-01-21 09:56:35 -080012956
12957 spy->assertNoEvents();
12958}
12959
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012960using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
12961
12962/**
12963 * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
12964 * are currently sent to any other windows - including other spy windows - will also be cancelled.
12965 */
12966TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
12967 auto window = createForeground();
12968 auto spy1 = createSpy();
12969 auto spy2 = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070012970 mDispatcher->onWindowInfosChanged(
12971 {{*spy1->getInfo(), *spy2->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012972
12973 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012974 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
12975 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012976 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12977 window->consumeMotionDown();
12978 spy1->consumeMotionDown();
12979 spy2->consumeMotionDown();
12980
12981 // Pilfer pointers from the second spy window.
12982 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
12983 spy2->assertNoEvents();
12984 spy1->consumeMotionCancel();
12985 window->consumeMotionCancel();
12986
12987 // The rest of the gesture should only be sent to the second spy window.
12988 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070012989 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070012990 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000012991 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
12992 spy2->consumeMotionMove();
12993 spy1->assertNoEvents();
12994 window->assertNoEvents();
12995}
12996
12997/**
12998 * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
12999 * in the middle of the gesture.
13000 */
13001TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
13002 auto window = createForeground();
13003 auto spy = createSpy();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013004 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013005
13006 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013007 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13008 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013009 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013010 window->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
13011 spy->consumeMotionDown(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013012
13013 window->releaseChannel();
13014
13015 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13016
13017 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013018 injectMotionUp(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13019 ui::LogicalDisplayId::DEFAULT))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013020 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013021 spy->consumeMotionUp(ui::LogicalDisplayId::DEFAULT);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013022}
13023
13024/**
13025 * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
13026 * the spy, but not to any other windows.
13027 */
13028TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
13029 auto spy = createSpy();
13030 auto window = createForeground();
13031
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013032 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013033
13034 // First finger down on the window and the spy.
13035 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013036 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13037 ui::LogicalDisplayId::DEFAULT, {100, 200}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013038 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13039 spy->consumeMotionDown();
13040 window->consumeMotionDown();
13041
13042 // Spy window pilfers the pointers.
13043 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13044 window->consumeMotionCancel();
13045
13046 // Second finger down on the window and spy, but the window should not receive the pointer down.
13047 const MotionEvent secondFingerDownEvent =
13048 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013049 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013050 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013051 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13052 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013053 .build();
13054 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013055 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013056 InputEventInjectionSync::WAIT_FOR_RESULT))
13057 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13058
Harry Cutts33476232023-01-30 19:57:29 +000013059 spy->consumeMotionPointerDown(/*pointerIndex=*/1);
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013060
13061 // Third finger goes down outside all windows, so injection should fail.
13062 const MotionEvent thirdFingerDownEvent =
13063 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013064 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013065 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013066 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200))
13067 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
13068 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(-5).y(-5))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013069 .build();
13070 ASSERT_EQ(InputEventInjectionResult::FAILED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013071 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013072 InputEventInjectionSync::WAIT_FOR_RESULT))
Siarhei Vishniakou1ae72f12023-01-29 12:55:30 -080013073 << "Inject motion event should return InputEventInjectionResult::FAILED";
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013074
13075 spy->assertNoEvents();
13076 window->assertNoEvents();
13077}
13078
13079/**
13080 * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
13081 */
13082TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
13083 auto spy = createSpy();
13084 spy->setFrame(Rect(0, 0, 100, 100));
13085 auto window = createForeground();
13086 window->setFrame(Rect(0, 0, 200, 200));
13087
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013088 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013089
13090 // First finger down on the window only
13091 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013092 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13093 ui::LogicalDisplayId::DEFAULT, {150, 150}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013094 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13095 window->consumeMotionDown();
13096
13097 // Second finger down on the spy and window
13098 const MotionEvent secondFingerDownEvent =
13099 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013100 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013101 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013102 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13103 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013104 .build();
13105 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013106 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013107 InputEventInjectionSync::WAIT_FOR_RESULT))
13108 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13109 spy->consumeMotionDown();
13110 window->consumeMotionPointerDown(1);
13111
13112 // Third finger down on the spy and window
13113 const MotionEvent thirdFingerDownEvent =
13114 MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013115 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013116 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013117 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(150).y(150))
13118 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(10).y(10))
13119 .pointer(PointerBuilder(/*id=*/2, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013120 .build();
13121 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013122 injectMotionEvent(*mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013123 InputEventInjectionSync::WAIT_FOR_RESULT))
13124 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13125 spy->consumeMotionPointerDown(1);
13126 window->consumeMotionPointerDown(2);
13127
13128 // Spy window pilfers the pointers.
13129 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Prabir Pradhan33cfc6d2024-06-11 20:17:44 +000013130 window->consumeMotionPointerUp(/*pointerIdx=*/2,
13131 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13132 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13133 WithPointerCount(3)));
13134 window->consumeMotionPointerUp(/*pointerIdx=*/1,
13135 AllOf(WithDisplayId(ui::LogicalDisplayId::DEFAULT),
13136 WithFlags(AMOTION_EVENT_FLAG_CANCELED),
13137 WithPointerCount(2)));
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013138
13139 spy->assertNoEvents();
13140 window->assertNoEvents();
13141}
13142
13143/**
13144 * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
13145 * other windows should be canceled. If this results in the cancellation of all pointers for some
13146 * window, then that window should receive ACTION_CANCEL.
13147 */
13148TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
13149 auto spy = createSpy();
13150 spy->setFrame(Rect(0, 0, 100, 100));
13151 auto window = createForeground();
13152 window->setFrame(Rect(0, 0, 200, 200));
13153
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013154 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013155
13156 // First finger down on both spy and window
13157 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013158 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13159 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013160 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13161 window->consumeMotionDown();
13162 spy->consumeMotionDown();
13163
13164 // Second finger down on the spy and window
13165 const MotionEvent secondFingerDownEvent =
13166 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013167 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013168 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013169 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13170 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(50).y(50))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013171 .build();
13172 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013173 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013174 InputEventInjectionSync::WAIT_FOR_RESULT))
13175 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13176 spy->consumeMotionPointerDown(1);
13177 window->consumeMotionPointerDown(1);
13178
13179 // Spy window pilfers the pointers.
13180 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13181 window->consumeMotionCancel();
13182
13183 spy->assertNoEvents();
13184 window->assertNoEvents();
13185}
13186
13187/**
13188 * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
13189 * be sent to other windows
13190 */
13191TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
13192 auto spy = createSpy();
13193 spy->setFrame(Rect(0, 0, 100, 100));
13194 auto window = createForeground();
13195 window->setFrame(Rect(0, 0, 200, 200));
13196
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013197 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013198
13199 // First finger down on both window and spy
13200 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013201 injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN,
13202 ui::LogicalDisplayId::DEFAULT, {10, 10}))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013203 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13204 window->consumeMotionDown();
13205 spy->consumeMotionDown();
13206
13207 // Spy window pilfers the pointers.
13208 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13209 window->consumeMotionCancel();
13210
13211 // Second finger down on the window only
13212 const MotionEvent secondFingerDownEvent =
13213 MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013214 .displayId(ui::LogicalDisplayId::DEFAULT)
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013215 .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013216 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(10).y(10))
13217 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(150))
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013218 .build();
13219 ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013220 injectMotionEvent(*mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
Vaibhav Devmurariff798f32022-05-09 23:45:04 +000013221 InputEventInjectionSync::WAIT_FOR_RESULT))
13222 << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
13223 window->consumeMotionDown();
13224 window->assertNoEvents();
13225
13226 // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
13227 spy->consumeMotionMove();
13228 spy->assertNoEvents();
13229}
13230
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013231/**
13232 * A window on the left and a window on the right. Also, a spy window that's above all of the
13233 * windows, and spanning both left and right windows.
13234 * Send simultaneous motion streams from two different devices, one to the left window, and another
13235 * to the right window.
13236 * Pilfer from spy window.
13237 * Check that the pilfering only affects the pointers that are actually being received by the spy.
13238 */
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013239TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer_legacy) {
13240 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013241 sp<FakeWindowHandle> spy = createSpy();
13242 spy->setFrame(Rect(0, 0, 200, 200));
13243 sp<FakeWindowHandle> leftWindow = createForeground();
13244 leftWindow->setFrame(Rect(0, 0, 100, 100));
13245
13246 sp<FakeWindowHandle> rightWindow = createForeground();
13247 rightWindow->setFrame(Rect(100, 0, 200, 100));
13248
13249 constexpr int32_t stylusDeviceId = 1;
13250 constexpr int32_t touchDeviceId = 2;
13251
13252 mDispatcher->onWindowInfosChanged(
13253 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13254
13255 // Stylus down on left window and spy
13256 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13257 .deviceId(stylusDeviceId)
13258 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13259 .build());
13260 leftWindow->consumeMotionEvent(
13261 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13262 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13263
13264 // Finger down on right window and spy - but spy already has stylus
13265 mDispatcher->notifyMotion(
13266 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13267 .deviceId(touchDeviceId)
13268 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13269 .build());
13270 rightWindow->consumeMotionEvent(
13271 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013272 spy->assertNoEvents();
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013273
13274 // Act: pilfer from spy. Spy is currently receiving touch events.
13275 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013276 leftWindow->consumeMotionEvent(
13277 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013278 rightWindow->consumeMotionEvent(
13279 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13280
13281 // Continue movements from both stylus and touch. Touch will be delivered to spy, but not stylus
13282 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13283 .deviceId(stylusDeviceId)
13284 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13285 .build());
13286 mDispatcher->notifyMotion(
13287 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13288 .deviceId(touchDeviceId)
13289 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13290 .build());
Siarhei Vishniakou2899c552023-07-10 18:20:46 -070013291 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakou0b251a32023-09-20 16:24:42 -070013292
13293 spy->assertNoEvents();
13294 leftWindow->assertNoEvents();
13295 rightWindow->assertNoEvents();
13296}
13297
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013298/**
13299 * A window on the left and a window on the right. Also, a spy window that's above all of the
13300 * windows, and spanning both left and right windows.
13301 * Send simultaneous motion streams from two different devices, one to the left window, and another
13302 * to the right window.
13303 * Pilfer from spy window.
13304 * Check that the pilfering affects all of the pointers that are actually being received by the spy.
13305 * The spy should receive both the touch and the stylus events after pilfer.
13306 */
13307TEST_F(InputDispatcherPilferPointersTest, MultiDevicePilfer) {
13308 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13309 sp<FakeWindowHandle> spy = createSpy();
13310 spy->setFrame(Rect(0, 0, 200, 200));
13311 sp<FakeWindowHandle> leftWindow = createForeground();
13312 leftWindow->setFrame(Rect(0, 0, 100, 100));
13313
13314 sp<FakeWindowHandle> rightWindow = createForeground();
13315 rightWindow->setFrame(Rect(100, 0, 200, 100));
13316
13317 constexpr int32_t stylusDeviceId = 1;
13318 constexpr int32_t touchDeviceId = 2;
13319
13320 mDispatcher->onWindowInfosChanged(
13321 {{*spy->getInfo(), *leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
13322
13323 // Stylus down on left window and spy
13324 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_STYLUS)
13325 .deviceId(stylusDeviceId)
13326 .pointer(PointerBuilder(0, ToolType::STYLUS).x(50).y(50))
13327 .build());
13328 leftWindow->consumeMotionEvent(
13329 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13330 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(stylusDeviceId)));
13331
13332 // Finger down on right window and spy
13333 mDispatcher->notifyMotion(
13334 MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13335 .deviceId(touchDeviceId)
13336 .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
13337 .build());
13338 rightWindow->consumeMotionEvent(
13339 AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13340 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(touchDeviceId)));
13341
13342 // Act: pilfer from spy. Spy is currently receiving touch events.
13343 EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
13344 leftWindow->consumeMotionEvent(
13345 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(stylusDeviceId)));
13346 rightWindow->consumeMotionEvent(
13347 AllOf(WithMotionAction(ACTION_CANCEL), WithDeviceId(touchDeviceId)));
13348
13349 // Continue movements from both stylus and touch. Touch and stylus will be delivered to spy
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013350 // Instead of sending the two MOVE events for each input device together, and then receiving
13351 // them both, process them one at at time. InputConsumer is always in the batching mode, which
13352 // means that the two MOVE events will be initially put into a batch. Once the events are
13353 // batched, the 'consume' call may result in any of the MOVE events to be sent first (depending
13354 // on the implementation of InputConsumer), which would mean that the order of the received
13355 // events could be different depending on whether there are 1 or 2 events pending in the
13356 // InputChannel at the time the test calls 'consume'. To make assertions simpler here, and to
13357 // avoid this confusing behaviour, send and receive each MOVE event separately.
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013358 mDispatcher->notifyMotion(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_STYLUS)
13359 .deviceId(stylusDeviceId)
13360 .pointer(PointerBuilder(0, ToolType::STYLUS).x(51).y(52))
13361 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013362 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(stylusDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013363 mDispatcher->notifyMotion(
13364 MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
13365 .deviceId(touchDeviceId)
13366 .pointer(PointerBuilder(0, ToolType::FINGER).x(151).y(52))
13367 .build());
Siarhei Vishniakou92bca1c2024-04-01 14:06:59 -070013368 spy->consumeMotionEvent(AllOf(WithMotionAction(ACTION_MOVE), WithDeviceId(touchDeviceId)));
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013369
13370 spy->assertNoEvents();
13371 leftWindow->assertNoEvents();
13372 rightWindow->assertNoEvents();
13373}
13374
Prabir Pradhan9cd9eb62023-11-22 17:58:06 +000013375TEST_F(InputDispatcherPilferPointersTest, NoPilferingWithHoveringPointers) {
13376 auto window = createForeground();
13377 auto spy = createSpy();
13378 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
13379
13380 mDispatcher->notifyMotion(
13381 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE)
13382 .deviceId(1)
13383 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(100).y(200))
13384 .build());
13385 window->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13386 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13387
13388 // Pilfer pointers from the spy window should fail.
13389 EXPECT_NE(OK, mDispatcher->pilferPointers(spy->getToken()));
13390 spy->assertNoEvents();
13391 window->assertNoEvents();
13392}
13393
Prabir Pradhand65552b2021-10-07 11:23:50 -070013394class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
13395public:
13396 std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
13397 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13398 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013399 sp<FakeWindowHandle> overlay = sp<FakeWindowHandle>::make(overlayApplication, mDispatcher,
13400 "Stylus interceptor window",
13401 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013402 overlay->setFocusable(false);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013403 overlay->setOwnerInfo(gui::Pid{111}, gui::Uid{111});
Prabir Pradhan4d5c52f2022-01-31 08:52:10 -080013404 overlay->setTouchable(false);
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013405 overlay->setInterceptsStylus(true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013406 overlay->setTrustedOverlay(true);
13407
13408 std::shared_ptr<FakeApplicationHandle> application =
13409 std::make_shared<FakeApplicationHandle>();
13410 sp<FakeWindowHandle> window =
Siarhei Vishniakouaed7ad02022-08-03 15:04:33 -070013411 sp<FakeWindowHandle>::make(application, mDispatcher, "Application window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013412 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013413 window->setFocusable(true);
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013414 window->setOwnerInfo(gui::Pid{222}, gui::Uid{222});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013415
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013416 mDispatcher->setFocusedApplication(ui::LogicalDisplayId::DEFAULT, application);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013417 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013418 setFocusedWindow(window);
Harry Cutts33476232023-01-30 19:57:29 +000013419 window->consumeFocusEvent(/*hasFocus=*/true, /*inTouchMode=*/true);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013420 return {std::move(overlay), std::move(window)};
13421 }
13422
13423 void sendFingerEvent(int32_t action) {
Prabir Pradhan678438e2023-04-13 19:32:51 +000013424 mDispatcher->notifyMotion(
Prabir Pradhand65552b2021-10-07 11:23:50 -070013425 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013426 ui::LogicalDisplayId::DEFAULT, {PointF{20, 20}}));
Prabir Pradhand65552b2021-10-07 11:23:50 -070013427 }
13428
13429 void sendStylusEvent(int32_t action) {
13430 NotifyMotionArgs motionArgs =
13431 generateMotionArgs(action, AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013432 ui::LogicalDisplayId::DEFAULT, {PointF{30, 40}});
Siarhei Vishniakou6d73f832022-07-21 17:27:03 -070013433 motionArgs.pointerProperties[0].toolType = ToolType::STYLUS;
Prabir Pradhan678438e2023-04-13 19:32:51 +000013434 mDispatcher->notifyMotion(motionArgs);
Prabir Pradhand65552b2021-10-07 11:23:50 -070013435 }
13436};
13437
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013438using InputDispatcherStylusInterceptorDeathTest = InputDispatcherStylusInterceptorTest;
13439
13440TEST_F(InputDispatcherStylusInterceptorDeathTest, UntrustedOverlay_AbortsDispatcher) {
Siarhei Vishniakouad3b6822023-06-22 14:17:35 -070013441 testing::GTEST_FLAG(death_test_style) = "threadsafe";
Prabir Pradhana3ab87a2022-01-27 10:00:21 -080013442 ScopedSilentDeath _silentDeath;
13443
Prabir Pradhand65552b2021-10-07 11:23:50 -070013444 auto [overlay, window] = setupStylusOverlayScenario();
13445 overlay->setTrustedOverlay(false);
13446 // Configuring an untrusted overlay as a stylus interceptor should cause Dispatcher to abort.
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013447 ASSERT_DEATH(mDispatcher->onWindowInfosChanged(
13448 {{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0}),
Prabir Pradhand65552b2021-10-07 11:23:50 -070013449 ".* not a trusted overlay");
13450}
13451
13452TEST_F(InputDispatcherStylusInterceptorTest, ConsmesOnlyStylusEvents) {
13453 auto [overlay, window] = setupStylusOverlayScenario();
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013454 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013455
13456 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13457 overlay->consumeMotionDown();
13458 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13459 overlay->consumeMotionUp();
13460
13461 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13462 window->consumeMotionDown();
13463 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13464 window->consumeMotionUp();
13465
13466 overlay->assertNoEvents();
13467 window->assertNoEvents();
13468}
13469
13470TEST_F(InputDispatcherStylusInterceptorTest, SpyWindowStylusInterceptor) {
13471 auto [overlay, window] = setupStylusOverlayScenario();
Prabir Pradhan51e7db02022-02-07 06:02:57 -080013472 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013473 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhand65552b2021-10-07 11:23:50 -070013474
13475 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13476 overlay->consumeMotionDown();
13477 window->consumeMotionDown();
13478 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13479 overlay->consumeMotionUp();
13480 window->consumeMotionUp();
13481
13482 sendFingerEvent(AMOTION_EVENT_ACTION_DOWN);
13483 window->consumeMotionDown();
13484 sendFingerEvent(AMOTION_EVENT_ACTION_UP);
13485 window->consumeMotionUp();
13486
13487 overlay->assertNoEvents();
13488 window->assertNoEvents();
13489}
13490
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013491/**
13492 * Set up a scenario to test the behavior used by the stylus handwriting detection feature.
13493 * The scenario is as follows:
13494 * - The stylus interceptor overlay is configured as a spy window.
13495 * - The stylus interceptor spy receives the start of a new stylus gesture.
13496 * - It pilfers pointers and then configures itself to no longer be a spy.
13497 * - The stylus interceptor continues to receive the rest of the gesture.
13498 */
13499TEST_F(InputDispatcherStylusInterceptorTest, StylusHandwritingScenario) {
13500 auto [overlay, window] = setupStylusOverlayScenario();
13501 overlay->setSpy(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013502 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013503
13504 sendStylusEvent(AMOTION_EVENT_ACTION_DOWN);
13505 overlay->consumeMotionDown();
13506 window->consumeMotionDown();
13507
13508 // The interceptor pilfers the pointers.
13509 EXPECT_EQ(OK, mDispatcher->pilferPointers(overlay->getToken()));
13510 window->consumeMotionCancel();
13511
13512 // The interceptor configures itself so that it is no longer a spy.
13513 overlay->setSpy(false);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013514 mDispatcher->onWindowInfosChanged({{*overlay->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan6dfbf262022-03-14 15:24:30 +000013515
13516 // It continues to receive the rest of the stylus gesture.
13517 sendStylusEvent(AMOTION_EVENT_ACTION_MOVE);
13518 overlay->consumeMotionMove();
13519 sendStylusEvent(AMOTION_EVENT_ACTION_UP);
13520 overlay->consumeMotionUp();
13521
13522 window->assertNoEvents();
13523}
13524
Prabir Pradhan5735a322022-04-11 17:23:34 +000013525struct User {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013526 gui::Pid mPid;
Prabir Pradhan8a5c41d2023-06-08 19:13:46 +000013527 gui::Uid mUid;
Prabir Pradhan5735a322022-04-11 17:23:34 +000013528 uint32_t mPolicyFlags{DEFAULT_POLICY_FLAGS};
13529 std::unique_ptr<InputDispatcher>& mDispatcher;
13530
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013531 User(std::unique_ptr<InputDispatcher>& dispatcher, gui::Pid pid, gui::Uid uid)
Prabir Pradhan5735a322022-04-11 17:23:34 +000013532 : mPid(pid), mUid(uid), mDispatcher(dispatcher) {}
13533
13534 InputEventInjectionResult injectTargetedMotion(int32_t action) const {
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013535 return injectMotionEvent(*mDispatcher, action, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013536 ui::LogicalDisplayId::DEFAULT, {100, 200},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013537 {AMOTION_EVENT_INVALID_CURSOR_POSITION,
13538 AMOTION_EVENT_INVALID_CURSOR_POSITION},
13539 INJECT_EVENT_TIMEOUT, InputEventInjectionSync::WAIT_FOR_RESULT,
13540 systemTime(SYSTEM_TIME_MONOTONIC), {mUid}, mPolicyFlags);
13541 }
13542
13543 InputEventInjectionResult injectTargetedKey(int32_t action) const {
Linnan Li13bf76a2024-05-05 19:18:02 +080013544 return inputdispatcher::injectKey(*mDispatcher, action, /*repeatCount=*/0,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013545 ui::LogicalDisplayId::INVALID,
Prabir Pradhan5735a322022-04-11 17:23:34 +000013546 InputEventInjectionSync::WAIT_FOR_RESULT,
Harry Cutts33476232023-01-30 19:57:29 +000013547 INJECT_EVENT_TIMEOUT, /*allowKeyRepeat=*/false, {mUid},
Prabir Pradhan5735a322022-04-11 17:23:34 +000013548 mPolicyFlags);
13549 }
13550
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013551 sp<FakeWindowHandle> createWindow(const char* name) const {
Prabir Pradhan5735a322022-04-11 17:23:34 +000013552 std::shared_ptr<FakeApplicationHandle> overlayApplication =
13553 std::make_shared<FakeApplicationHandle>();
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013554 sp<FakeWindowHandle> window =
13555 sp<FakeWindowHandle>::make(overlayApplication, mDispatcher, name,
13556 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013557 window->setOwnerInfo(mPid, mUid);
13558 return window;
13559 }
13560};
13561
13562using InputDispatcherTargetedInjectionTest = InputDispatcherTest;
13563
13564TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013565 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013566 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013567 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013568
13569 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13570 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13571 window->consumeMotionDown();
13572
13573 setFocusedWindow(window);
13574 window->consumeFocusEvent(true);
13575
13576 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13577 owner.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013578 window->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013579}
13580
13581TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013582 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013583 auto window = owner.createWindow("Owned window");
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013584 mDispatcher->onWindowInfosChanged({{*window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013585
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013586 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013587 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13588 rando.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13589
13590 setFocusedWindow(window);
13591 window->consumeFocusEvent(true);
13592
13593 EXPECT_EQ(InputEventInjectionResult::TARGET_MISMATCH,
13594 rando.injectTargetedKey(AKEY_EVENT_ACTION_DOWN));
13595 window->assertNoEvents();
13596}
13597
13598TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoOwnedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013599 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013600 auto window = owner.createWindow("Owned window");
13601 auto spy = owner.createWindow("Owned spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013602 spy->setSpy(true);
13603 spy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013604 mDispatcher->onWindowInfosChanged({{*spy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013605
13606 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13607 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13608 spy->consumeMotionDown();
13609 window->consumeMotionDown();
13610}
13611
13612TEST_F(InputDispatcherTargetedInjectionTest, CannotInjectIntoUnownedSpyWindow) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013613 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013614 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013615
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013616 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013617 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013618 randosSpy->setSpy(true);
13619 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013620 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013621
13622 // The event is targeted at owner's window, so injection should succeed, but the spy should
13623 // not receive the event.
13624 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13625 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13626 randosSpy->assertNoEvents();
13627 window->consumeMotionDown();
13628}
13629
13630TEST_F(InputDispatcherTargetedInjectionTest, CanInjectIntoAnyWindowWhenNotTargeting) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013631 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013632 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013633
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013634 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013635 auto randosSpy = rando.createWindow("Rando's spy");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013636 randosSpy->setSpy(true);
13637 randosSpy->setTrustedOverlay(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013638 mDispatcher->onWindowInfosChanged({{*randosSpy->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013639
13640 // A user that has injection permission can inject into any window.
13641 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013642 injectMotionEvent(*mDispatcher, AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013643 ui::LogicalDisplayId::DEFAULT));
Prabir Pradhan5735a322022-04-11 17:23:34 +000013644 randosSpy->consumeMotionDown();
13645 window->consumeMotionDown();
13646
13647 setFocusedWindow(randosSpy);
13648 randosSpy->consumeFocusEvent(true);
13649
Siarhei Vishniakoub237f9e2023-07-21 16:42:23 -070013650 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED, injectKeyDown(*mDispatcher));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013651 randosSpy->consumeKeyDown(ui::LogicalDisplayId::INVALID);
Prabir Pradhan5735a322022-04-11 17:23:34 +000013652 window->assertNoEvents();
13653}
13654
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013655TEST_F(InputDispatcherTargetedInjectionTest, CannotGenerateActionOutsideToOtherUids) {
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013656 auto owner = User(mDispatcher, gui::Pid{10}, gui::Uid{11});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013657 auto window = owner.createWindow("Owned window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013658
Prabir Pradhanaeebeb42023-06-13 19:53:03 +000013659 auto rando = User(mDispatcher, gui::Pid{20}, gui::Uid{21});
Siarhei Vishniakoue3ce4122023-08-23 10:26:46 -070013660 auto randosWindow = rando.createWindow("Rando's window");
Prabir Pradhan5735a322022-04-11 17:23:34 +000013661 randosWindow->setFrame(Rect{-10, -10, -5, -5});
13662 randosWindow->setWatchOutsideTouch(true);
Siarhei Vishniakouc41de372023-07-20 13:14:26 -070013663 mDispatcher->onWindowInfosChanged({{*randosWindow->getInfo(), *window->getInfo()}, {}, 0, 0});
Prabir Pradhan5735a322022-04-11 17:23:34 +000013664
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013665 // Do not allow generation of ACTION_OUTSIDE events into windows owned by different uids.
Prabir Pradhan5735a322022-04-11 17:23:34 +000013666 EXPECT_EQ(InputEventInjectionResult::SUCCEEDED,
13667 owner.injectTargetedMotion(AMOTION_EVENT_ACTION_DOWN));
13668 window->consumeMotionDown();
Siarhei Vishniakou580fb3a2023-05-05 15:02:20 -070013669 randosWindow->assertNoEvents();
Prabir Pradhan5735a322022-04-11 17:23:34 +000013670}
13671
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013672using InputDispatcherPointerInWindowTest = InputDispatcherTest;
13673
13674TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWhenHovering) {
13675 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13676
13677 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013678 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013679 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013680 sp<FakeWindowHandle> right =
13681 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13682 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013683 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013684 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13685 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013686 spy->setFrame(Rect(0, 0, 200, 100));
13687 spy->setTrustedOverlay(true);
13688 spy->setSpy(true);
13689
13690 mDispatcher->onWindowInfosChanged(
13691 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13692
13693 // Hover into the left window.
13694 mDispatcher->notifyMotion(
13695 MotionArgsBuilder(ACTION_HOVER_ENTER, AINPUT_SOURCE_STYLUS)
13696 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(50).y(50))
13697 .build());
13698
13699 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13700 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13701
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013702 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13703 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013704 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013705 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13706 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013707 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013708 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13709 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013710 /*pointerId=*/0));
13711
13712 // Hover move to the right window.
13713 mDispatcher->notifyMotion(
13714 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_STYLUS)
13715 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13716 .build());
13717
13718 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13719 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13720 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_MOVE));
13721
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013722 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13723 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013724 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013725 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13726 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013727 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013728 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13729 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013730 /*pointerId=*/0));
13731
13732 // Stop hovering.
13733 mDispatcher->notifyMotion(
13734 MotionArgsBuilder(ACTION_HOVER_EXIT, AINPUT_SOURCE_STYLUS)
13735 .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(150).y(50))
13736 .build());
13737
13738 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13739 spy->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13740
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013741 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13742 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013743 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013744 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13745 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013746 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013747 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13748 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013749 /*pointerId=*/0));
13750}
13751
13752TEST_F(InputDispatcherPointerInWindowTest, PointerInWindowWithSplitTouch) {
13753 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13754
13755 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013756 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013757 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013758 sp<FakeWindowHandle> right =
13759 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13760 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013761 right->setFrame(Rect(100, 0, 200, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013762 sp<FakeWindowHandle> spy = sp<FakeWindowHandle>::make(application, mDispatcher, "Spy Window",
13763 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013764 spy->setFrame(Rect(0, 0, 200, 100));
13765 spy->setTrustedOverlay(true);
13766 spy->setSpy(true);
13767
13768 mDispatcher->onWindowInfosChanged(
13769 {{*spy->getInfo(), *left->getInfo(), *right->getInfo()}, {}, 0, 0});
13770
13771 // First pointer down on left window.
13772 mDispatcher->notifyMotion(
13773 MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13774 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13775 .build());
13776
13777 left->consumeMotionDown();
13778 spy->consumeMotionDown();
13779
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013780 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13781 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013782 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013783 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13784 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013785 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013786 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13787 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013788 /*pointerId=*/0));
13789
13790 // Second pointer down on right window.
13791 mDispatcher->notifyMotion(
13792 MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
13793 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13794 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13795 .build());
13796
13797 left->consumeMotionMove();
13798 right->consumeMotionDown();
13799 spy->consumeMotionEvent(WithMotionAction(POINTER_1_DOWN));
13800
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013801 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13802 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013803 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013804 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13805 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013806 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013807 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13808 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013809 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013810 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13811 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013812 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013813 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13814 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013815 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013816 ASSERT_TRUE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13817 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013818 /*pointerId=*/1));
13819
13820 // Second pointer up.
13821 mDispatcher->notifyMotion(
13822 MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
13823 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13824 .pointer(PointerBuilder(/*id=*/1, ToolType::FINGER).x(150).y(50))
13825 .build());
13826
13827 left->consumeMotionMove();
13828 right->consumeMotionUp();
13829 spy->consumeMotionEvent(WithMotionAction(POINTER_1_UP));
13830
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013831 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13832 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013833 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013834 ASSERT_TRUE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13835 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013836 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013837 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13838 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013839 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013840 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13841 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013842 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013843 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13844 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013845 /*pointerId=*/1));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013846 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13847 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013848 /*pointerId=*/1));
13849
13850 // First pointer up.
13851 mDispatcher->notifyMotion(
13852 MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
13853 .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER).x(50).y(50))
13854 .build());
13855
13856 left->consumeMotionUp();
13857 spy->consumeMotionUp();
13858
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013859 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13860 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013861 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013862 ASSERT_FALSE(mDispatcher->isPointerInWindow(spy->getToken(), ui::LogicalDisplayId::DEFAULT,
13863 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013864 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013865 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13866 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013867 /*pointerId=*/0));
13868}
13869
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013870TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse_legacy) {
13871 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013872 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13873
13874 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013875 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013876 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013877 sp<FakeWindowHandle> right =
13878 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13879 ui::LogicalDisplayId::DEFAULT);
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013880 right->setFrame(Rect(100, 0, 200, 100));
13881
13882 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
13883
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013884 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13885 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013886 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013887 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13888 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013889 /*pointerId=*/0));
13890
13891 // Hover move into the window.
13892 mDispatcher->notifyMotion(
13893 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13894 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
13895 .rawXCursorPosition(50)
13896 .rawYCursorPosition(50)
13897 .deviceId(DEVICE_ID)
13898 .build());
13899
13900 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13901
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013902 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13903 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013904 /*pointerId=*/0));
13905
13906 // Move the mouse with another device. This cancels the hovering pointer from the first device.
13907 mDispatcher->notifyMotion(
13908 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13909 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
13910 .rawXCursorPosition(51)
13911 .rawYCursorPosition(50)
13912 .deviceId(SECOND_DEVICE_ID)
13913 .build());
13914
13915 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13916 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13917
13918 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
13919 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013920 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13921 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013922 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013923 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013924 SECOND_DEVICE_ID,
13925 /*pointerId=*/0));
13926
13927 // Move the mouse outside the window. Document the current behavior, where the window does not
13928 // receive HOVER_EXIT even though the mouse left the window.
13929 mDispatcher->notifyMotion(
13930 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13931 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
13932 .rawXCursorPosition(150)
13933 .rawYCursorPosition(50)
13934 .deviceId(SECOND_DEVICE_ID)
13935 .build());
13936
13937 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
13938 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013939 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13940 DEVICE_ID,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013941 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013942 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Prabir Pradhan64f21d22023-11-28 21:19:42 +000013943 SECOND_DEVICE_ID,
13944 /*pointerId=*/0));
13945}
13946
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013947/**
13948 * TODO(b/313689709) - correctly support multiple mouse devices, because they should be controlling
13949 * the same cursor, and therefore have a shared motion event stream.
13950 */
13951TEST_F(InputDispatcherPointerInWindowTest, MultipleDevicesControllingOneMouse) {
13952 SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
13953 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
13954
13955 sp<FakeWindowHandle> left = sp<FakeWindowHandle>::make(application, mDispatcher, "Left Window",
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013956 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013957 left->setFrame(Rect(0, 0, 100, 100));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013958 sp<FakeWindowHandle> right =
13959 sp<FakeWindowHandle>::make(application, mDispatcher, "Right Window",
13960 ui::LogicalDisplayId::DEFAULT);
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013961 right->setFrame(Rect(100, 0, 200, 100));
13962
13963 mDispatcher->onWindowInfosChanged({{*left->getInfo(), *right->getInfo()}, {}, 0, 0});
13964
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013965 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13966 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013967 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013968 ASSERT_FALSE(mDispatcher->isPointerInWindow(right->getToken(), ui::LogicalDisplayId::DEFAULT,
13969 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013970 /*pointerId=*/0));
13971
13972 // Hover move into the window.
13973 mDispatcher->notifyMotion(
13974 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13975 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(50).y(50))
13976 .rawXCursorPosition(50)
13977 .rawYCursorPosition(50)
13978 .deviceId(DEVICE_ID)
13979 .build());
13980
13981 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13982
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013983 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
13984 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070013985 /*pointerId=*/0));
13986
13987 // Move the mouse with another device
13988 mDispatcher->notifyMotion(
13989 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
13990 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(51).y(50))
13991 .rawXCursorPosition(51)
13992 .rawYCursorPosition(50)
13993 .deviceId(SECOND_DEVICE_ID)
13994 .build());
13995 left->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
13996
13997 // TODO(b/313689709): InputDispatcher's touch state is not updated, even though the window gets
13998 // a HOVER_EXIT from the first device.
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070013999 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14000 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014001 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014002 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014003 SECOND_DEVICE_ID,
14004 /*pointerId=*/0));
14005
14006 // Move the mouse outside the window. Document the current behavior, where the window does not
14007 // receive HOVER_EXIT even though the mouse left the window.
14008 mDispatcher->notifyMotion(
14009 MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14010 .pointer(PointerBuilder(/*id=*/0, ToolType::MOUSE).x(150).y(50))
14011 .rawXCursorPosition(150)
14012 .rawYCursorPosition(50)
14013 .deviceId(SECOND_DEVICE_ID)
14014 .build());
14015
14016 right->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014017 ASSERT_TRUE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
14018 DEVICE_ID,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014019 /*pointerId=*/0));
Siarhei Vishniakoucfbee532024-05-10 13:41:35 -070014020 ASSERT_FALSE(mDispatcher->isPointerInWindow(left->getToken(), ui::LogicalDisplayId::DEFAULT,
Siarhei Vishniakoued89cbb2023-10-13 10:42:44 -070014021 SECOND_DEVICE_ID,
14022 /*pointerId=*/0));
14023}
14024
Arpit Singhb65e2bd2024-06-03 09:48:16 +000014025TEST_F(InputDispatcherTest, FocusedDisplayChangeIsNotified) {
14026 mDispatcher->setFocusedDisplay(SECOND_DISPLAY_ID);
14027 mFakePolicy->assertFocusedDisplayNotified(SECOND_DISPLAY_ID);
14028}
14029
Garfield Tane84e6f92019-08-29 17:28:41 -070014030} // namespace android::inputdispatcher